I begin by defining a large integer n
:
Prelude> let n = 5705979550618670446308578858542675373983
Prelude> n :: Integer
5705979550618670446308578858542675373983
Next I looked at the behavior of s1
and s2
:
Prelude> let s1 = (sqrt (fromIntegral n))^2
Prelude> let s2 = (floor(sqrt(fromIntegral n)))^2
Prelude> s1 == fromIntegral n
True
Prelude> s1 == fromIntegral s2
True
Prelude> (fromIntegral n) == (fromIntegral s2)
False
Since any fractional part might be discarded, equality on the last 2 expressions was not expected. However, I didn't expect equality to be intransitive (e.g. n == s1, s1 == s2
, but n != s2
.)
Furthermore, floor
appears to lose precision on the integer part, despite retaining 40 significant digits.
Prelude> s1
5.70597955061867e39
Prelude> s2
5705979550618669899723442048678773129216
This lost precision becomes obvious when testing subtraction:
Prelude> (fromIntegral n) - s1
0.0
Prelude> (fromIntegral n) - (fromIntegral s2)
546585136809863902244767
Why does floor
lose precision, and how is this violating transitivity of equality (if at all)?
What is the best approach to computing floor . sqrt
without loss of precision?