将Int转换为Float会失去Swift中大数字的精度
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.为什么?
这是由于浮点格式的工作方式。 Float
是一个32位浮点数,以IEEE 754格式存储,基本上是科学记数法,有些位分配给该值,有些位分配给指数(在基数2中),如图所示-precision浮点数维基百科文章显示:
所以实际数字表示为
(sign) * (value) * (2 ^ (exponent))
因为分配给实际存储整数值(24)的比特数小于在普通整数(全部32)中为此分配的比特数,所以为了给指数腾出空间,大数字的较低有效位数将被牺牲,以换取表示几乎无限数的能力(正常的Int
只能表示-2 ^ 31到2 ^ 31-1范围内的整数)。
一些粗略的测试表明,直到16777216 ( 2 ^ 24 )的每个整数都可以精确地表示在32位浮点数中,而较大的整数将四舍五入到最接近2的幂的倍数。
请注意,这不是Swift特有的。 这种浮点格式是几乎所有编程语言中使用的标准格式。 这是我使用普通C从LLDB获得的输出:
如果您需要更高的精度,请使用Double
。 双精度浮点数使用64位内存,具有更高的精度。
32位浮点数只能容纳约7-9个有效数字。 如果需要更多数字,精度将会丢失。
请参阅java中有多少有效数字具有浮点数和双精度数? 用于计算。
在Swift中,你可以使用Double
,它可以容纳更多数字(64位浮点数)或NSDecimalNumber
,它以十进制格式保存数字,并且不会丢失精度,因此它特别适合财务计算。 但是,性能要差得多。