2015-01-07 22 views
7

In Swift, c'è un modo per troncare un float a 2 decimali, in modo da poter eseguire ulteriori calcoli con esso? Tutti i thread che ho visto riguardano il casting su una stringa, che non riesco a capire come utilizzare matematicamente.Il modo più semplice per troncare il float a 2 cifre decimali?

Ho provato a utilizzare un'estensione (trovata in questo forum), immaginando di poter tornare indietro a float dopo il troncamento, ma finisco dove ho iniziato, con un altro float non troncato. Ho bisogno del mio valore di ritorno per essere in passi trimestre (vale a dire 6,50, 6,75, 5,25, ecc), e quello che sto finendo con, sono risultati come 6,990,022 mila ....

Ci deve essere un modo semplice per fai questo, ma sto colpendo un muro. Grazie in anticipo ...

Ecco il problema:

func roundToNearestQuarter(#power : Float) -> String { 

    var errorToLowerQuarterRaw : Float = power % 0.25 // 0.210000038146973 

    var errorToLowerQuarterString = errorToLowerQuarterStepRaw.string(2) // "0.21" 

    var errorToLowerQuarter = NSString(string: errorToLowerQuaterStepString).floatValue // 0.209999993443489 

// more code 

} 

roundToNearestQuater(6.71) 
+0

Se ha cifre decimali non è 'float'. Il 'float' di Swift è binario. –

risposta

10

È non può intorno a un Float o Double a 2 cifre decimali esattamente. La ragione è che questi tipi di dati utilizzano una rappresentazione binario in virgola mobile, e non possono rappresentare numeri come 0,1 o 0,01 esattamente. Si veda ad esempio

Ma lei ha detto:

ho bisogno del mio valore di ritorno per essere in passi trimestre (vale a dire 6,50, 6,75, 5,25, ecc),

e che è esattamente possibile perché 0,25 = 2 -2 può essere rappresentato esattamente come un numero decimale.

La funzione round() arrotonda un numero in virgola mobile al valore integrale più vicino. Per arrotondare al trimestre più vicino, basta a "scala" il calcolo con il fattore 4:

func roundToNearestQuarter(num : Float) -> Float { 
    return round(num * 4.0)/4.0 
} 

roundToNearestQuarter(6.71) // 6.75 
roundToNearestQuarter(6.6) // 6.5 
+0

Grazie per la risposta, è molto istruttivo :) – EridB

+0

@ Attackfarm: Perché la pensi così? Tutto ciò che viene detto in questa risposta è vero anche per Double. –

+0

@Attackfarm: Potrebbe * sembrare * che un Double memorizza esattamente tutti i numeri, poiché println() arrotonda l'output a 6 decimali e Double ha una precisione di circa 15 decimali. Ma prova 'lascia x = 0.1; sia y = 0,2; println (x + y - 0.3) '... –

0

Se avete bisogno di lavorare con la vera precisione (per le applicazioni di valute legate, per esempio), si vuole probabilmente vuoi usare NSDecimalNumber invece di virgola mobile.

L'approccio di cui sopra può essere applicato a NSDecimalNumbers come mostrato di seguito. In questo esempio, il "passaggio" a cui stai arrotondando può essere qualsiasi cosa tu scelga, basta impostare "incrementa" di conseguenza.

let number: NSDecimalNumber = 100.52 
let increment: NSDecimalNumber = 0.25 

let handler = NSDecimalNumberHandler(roundingMode: NSRoundingMode.RoundBankers, scale: 0, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)  // Rounds to the nearest whole number 
let result = number.decimalNumberByDividingBy(increment).decimalNumberByRoundingAccordingToBehavior(handler).decimalNumberByMultiplyingBy(increment) 

Per maggiori informazioni su arrotondamento con NSDecimalNumber vedere qui: How to round an NSDecimalNumber in swift?

E sì, lavorando con NSDecimalNumber è un modo terribilmente verboso di fare matematica, ma non è complicato. Se ti ritrovi a fare un progetto che li coinvolge frequentemente, ti consiglio di configurare le estensioni dell'operatore Swift in modo da poterle manipolare in modo più elegante. Controlla qui per un bell'esempio: https://gist.github.com/mattt/1ed12090d7c89f36fd28