将Int转换为Float在Swift中失去了大量的精度 [英] Converting Int to Float loses precision for large numbers in Swift

查看:235
本文介绍了将Int转换为Float在Swift中失去了大量的精度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

XCode 6.3.1 Swift 1.2

let value:Int = 220904525
let intmax = Int.max
let float = Float(value)//这可能是一个错误
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位浮点数,存储在,这基本上是科学记数法,其中一些位分配给值,另一些分配给指数(以2为底),如图所示:单精度浮点数维基百科文章显示:



所以实际的数字表示为

 (sign)*(value)*(2 ^(exponent))
Int
只能表示-2 ^ 31到2 ^ 31 - 1范围内的整数)。



一些粗略的测试表明,每个小于16777216 的整数( 2 ^ 24 )都可以精确地表示为 >在一个32位的浮点数,而较大的整数将四舍五入到2的某个幂的最接近的倍数。

请注意,这不是特定于Swift。这种浮点格式是几乎所有编程语言都使用的标准格式。这里是我从LLDB以纯C获得的输出: b
$ b



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

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

The initial value is 220904525. But when I convert it to float it becomes 220904528. Why?

解决方案

This is due to the way the floating-point format works. A Float is a 32-bit floating-point number, stored in the 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 shows:

So the actual number is represented as

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

Because the number of bits allocated to actually storing an integer value (24) is smaller than the number of bits allocated for this in a normal integer (all 32), in order to make room for the exponent, the less significant digits of large numbers will be sacrificed, in exchange for the ability to represent almost infinite numbers (a normal Int can only represent integers in the range -2^31 to 2^31 - 1).

Some rough testing indicates that every integer up to and including 16777216 (2 ^ 24) can be represented exactly in a 32-bit float, while larger integers will be rounded to the nearest multiple of some power of 2.

Note that this isn't specific to Swift. This floating-point format is a standard format used in almost every programming language. Here's the output I get from LLDB with plain C:

If you need higher precision, use a Double. Double precision floats use 64 bits of memory, and have higher precision.

这篇关于将Int转换为Float在Swift中失去了大量的精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆