对于 Swift 中的大数字,将 Int 转换为 Float 会失去精度
Converting Int to Float loses precision for large numbers in Swift
XCode6.3.1Swift1.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,为什么?
一个32位的浮点数只能容纳大约7-9位有效数字。如果你需要更多的数字,精度将会丢失。
有关计算,请参阅 How many significant digits have floats and doubles in java?。
在 Swift 中,您可以使用 Double
可以容纳更多数字(64 位浮点数)或 NSDecimalNumber
可以容纳十进制格式的数字并且不会丢失精度所以它是特别适合财务计算。但是,性能差很多。
这是由于浮点格式的工作方式所致。 Float
是一个32位的浮点数,存放在IEEE 754 format, which is basically scientific notation, with some bits allocated to the value, and some to the exponent (in base 2), as this diagram from the single-precision floating-point number Wikipedia article中说明:
所以实际的数字表示为
(sign) * (value) * (2 ^ (exponent))
因为分配给实际存储一个整数值的位数(24)比普通整数分配给这个的位数(都是32)少,为了给指数腾出空间,越少大数的有效数字将被牺牲,以换取表示几乎无穷大数的能力(普通的 Int
只能表示 -2^31 到 2^31 - 1 范围内的整数)。
一些粗略的测试表明,直到并包括 16777216 (2 ^ 24) 的每个整数都可以表示 在 32 位浮点数中正好,而较大的整数将四舍五入到最接近的 2 的某个幂的倍数。
请注意,这并非特定于 Swift。这种浮点格式是几乎所有编程语言都使用的标准格式。这是我使用纯 C:
从 LLDB 获得的输出
如果您需要更高的精度,请使用 Double
。双精度浮点数使用64位内存,精度更高
XCode6.3.1Swift1.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,为什么?
一个32位的浮点数只能容纳大约7-9位有效数字。如果你需要更多的数字,精度将会丢失。
有关计算,请参阅 How many significant digits have floats and doubles in java?。
在 Swift 中,您可以使用 Double
可以容纳更多数字(64 位浮点数)或 NSDecimalNumber
可以容纳十进制格式的数字并且不会丢失精度所以它是特别适合财务计算。但是,性能差很多。
这是由于浮点格式的工作方式所致。 Float
是一个32位的浮点数,存放在IEEE 754 format, which is basically scientific notation, with some bits allocated to the value, and some to the exponent (in base 2), as this diagram from the single-precision floating-point number Wikipedia article中说明:
所以实际的数字表示为
(sign) * (value) * (2 ^ (exponent))
因为分配给实际存储一个整数值的位数(24)比普通整数分配给这个的位数(都是32)少,为了给指数腾出空间,越少大数的有效数字将被牺牲,以换取表示几乎无穷大数的能力(普通的 Int
只能表示 -2^31 到 2^31 - 1 范围内的整数)。
一些粗略的测试表明,直到并包括 16777216 (2 ^ 24) 的每个整数都可以表示 在 32 位浮点数中正好,而较大的整数将四舍五入到最接近的 2 的某个幂的倍数。
请注意,这并非特定于 Swift。这种浮点格式是几乎所有编程语言都使用的标准格式。这是我使用纯 C:
从 LLDB 获得的输出如果您需要更高的精度,请使用 Double
。双精度浮点数使用64位内存,精度更高