Why is Math.sqrt(i*i).floor == i?

floating-point, precision, ruby

Solution

For "small" integers, there is usually an exact floating-point representation.

Problem

I am wondering if this is true: When I take the square root of a squared integer, like in ``` f = Math.sqrt(123*123) ``` I will get a floating point number very close to `123`. Due to floating point representation precision, this could be something like 122.99999999999999999999 or 123.000000000000000000001. Since `floor(122.999999999999999999)` is 122, I should get 122 instead of 123. So I expect that `floor(sqrt(i*i)) == i-1` in about 50% of the cases. Strangely, for all the numbers I have tested, `floor(sqrt(i*i) == i`. Here is a small ruby script to test the first 100 million numbers: ``` 100_000_000.times do |i| puts i if Math.sqrt(i*i).floor != i end ``` The above script never prints anything. Why is that so? UPDATE: Thanks for the quick reply, this seems to be the solution: According to wikipedia Any integer with absolute value less than or equal to 2^24 can be exactly represented in the single precision format, and any integer with absolute value less than or equal to 2^53 can be exactly represented in the double precision format. Math.sqrt(i*i) starts to behave as I've expected it starting from i=9007199254740993, which is 2^53 + 1.

Original source