6

XCode 6.3.1 Swift 1,2Conversione Int Float perde di precisione per un gran numero di Swift

let value: Int = 220904525 
let intmax = Int.max 
let float = Float(value) // Here is an error probably 
let intFromFloat = Int(float) 
let double = Double(value) 
println("intmax=\(intmax) value=\(value) float=\(float) intFromFloat=\(intFromFloat) double=\(double)") 
// intmax=9223372036854775807 value=220904525 float=2.20905e+08 intFromFloat=220904528 double=220904525.0 

Il valore iniziale è 220904525. Ma quando converto di galleggiare diventa 220904528. Perché?

+1

sì, è così che funziona il floating point. –

+1

possibile duplicato di [Perdita di precisione - int -> float o double] (http://stackoverflow.com/questions/2781086/loss-of-precision-int-float-or-double) –

+0

@TheParamagneticCroissant Penso che sia non duplicato perché in Swift questi tipi (Float Double Int) sono strutture e questo problema di valori float semplici può essere risolto – kostyl

risposta

10

Ciò è dovuto al modo in cui funziona il formato a virgola mobile. A Float è un numero a virgola mobile a 32 bit, memorizzato nello IEEE 754 format, che è in pratica una notazione scientifica, con alcuni bit allocati al valore e alcuni all'esponente (in base 2), in quanto questo diagramma da single-precision floating-point number Wikipedia article mostra:

32-bit float format

Così il numero effettivo è rappresentato come

(sign) * (value) * (2^(exponent)) 

poiché il numero di bit allocati a memorizzare in realtà un valore intero (24) è inferiore al numero di bit assegnato per questo in un normale intero (tutti 32), al fine di rendere r oom per l'esponente, le cifre meno significative di grandi numeri saranno sacrificate, in cambio della capacità di rappresentare numeri quasi infiniti (un normale Int può rappresentare solo interi nell'intervallo da -2^31 a 2^31 - 1).

Alcuni test approssimativa indica che ogni intero fino al (2^24) può essere rappresentato esattamente in un galleggiante 32 bit, mentre interi maggiori saranno arrotondati al multiplo più vicino di alcuni potenza di 2.

Si noti che questo non è specifico di Swift. Questo formato in virgola mobile è un formato standard utilizzato in quasi tutti i linguaggi di programmazione. Ecco l'output che ricevo da LLDB con piano C:

Se avete bisogno di una maggiore precisione, utilizzare un Double. I galleggianti a doppia precisione utilizzano 64 bit di memoria e hanno una precisione maggiore.

3

Un numero in virgola mobile a 32 bit può contenere solo circa 7-9 cifre significative. Se hai bisogno di più cifre, la precisione andrà persa.

Vedere How many significant digits have floats and doubles in java? per i calcoli.

In Swift, è possibile utilizzare Double che può contenere più cifre (float a 64 bit) o ​​NSDecimalNumber che contiene il numero in formato decimale e non perde la precisione, quindi è particolarmente utile per i calcoli finanziari. Tuttavia, la performance è molto peggiore.

Problemi correlati