Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Int to Float loses precision for large numbers in 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

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

like image 315
kostyl Avatar asked May 15 '15 13:05

kostyl


People also ask

What happens when you convert a float to an int?

Convert a float to an int always results in a data loss. The trunc() function returns the integer part of a number. The floor() function returns the largest integer less than or equal to a number. The ceil() function returns the smallest integer greater than or equal to a number.

Why use integers over floats and not just floats all the time?

The int type automatically promotes to long when a computation goes beyond its range, thereby retaining precision. float doesn't get bigger to remain precise.

Can you go from int to float?

To convert an integer data type to float you can wrap the integer with float64() or float32. Explanation: Firstly we declare a variable x of type int64 with a value of 5. Then we wrap x with float64(), which converts the integer 5 to float value of 5.00.

Are ints and floats the same size?

They are totally different - typically int is just a straightforward 2's complement signed integer, while float is a single precision floating point representation with 23 bits of mantissa, 8 bits exponent and 1 bit sign (see http://en.wikipedia.org/wiki/IEEE_754-2008).


1 Answers

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:

32-bit float format

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.

like image 141
Greg Avatar answered Sep 24 '22 14:09

Greg