Converting Int to Float loses precision for large numbers in Swift

时间秒杀一切 提交于 2019-11-28 12:16:38

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.

Sulthan

A 32bit floating point number can hold only about 7-9 significant digits. If you need more digits, the precision will be lost.

See How many significant digits have floats and doubles in java? for the calculations.

In Swift, you can use Double which can hold more digits (64bit float) or NSDecimalNumber which holds number in decimal format and doesn't lose precision so it is especially good for financial calculations. However, the performance is much worse.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!