将Int转换为Float会失去Swift中大数字的精度

时间:2015-05-15 13:28:32

标签: ios swift floating-point floating-point-precision floating-point-conversion

XCode 6.3.1 Swift 1.2

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

初始值是220904525.但是当我将其转换为浮动时,它变为220904528.为什么?

2 个答案:

答案 0 :(得分:11)

这是由于浮点格式的工作方式。 Float是一个32位浮点数,存储在IEEE 754 format中,基本上是科学记数法,其中一些位分配给该值,一些位分配给指数(在基数2中),正如single-precision floating-point number Wikipedia article显示的图表所示:

32-bit float format

所以实际数字表示为

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

因为分配给实际存储整数值(24)的比特数小于为普通整数(全部32)分配的比特数,为了给指数腾出空间,数字不太重要大量数字将被牺牲,以换取表示几乎无限数的能力(正常Int只能表示-2 ^ 31到2 ^ 31 - 1范围内的整数。

一些粗略的测试表明,在32位中, 16777216 2 ^ 24 )的每个整数都可以完全表示浮点数,而较大的整数将四舍五入到最接近2的幂的倍数。

请注意,这不是特定于Swift的。这种浮点格式是几乎所有编程语言中使用的标准格式。这是我从LLDB获得的带有普通C的输出:

如果您需要更高的精确度,请使用Double。双精度浮点数使用64位内存,具有更高的精度。

答案 1 :(得分:3)

32位浮点数只能保存约7-9位有效数字。如果您需要更多数字,精度将会丢失。

有关计算,请参阅How many significant digits have floats and doubles in java?

在Swift中,你可以使用Double,它可以容纳更多的数字(64位浮点数)或NSDecimalNumber,它以十进制格式保存数字,并且不会丢失精度,因此它特别适合财务计算。但是,性能要差得多。