我首先定义一个大整数n
:
Prelude> let n = 5705979550618670446308578858542675373983
Prelude> n :: Integer
5705979550618670446308578858542675373983
接下来我查看了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
由于可能会丢弃任何小数部分,因此不期望最后 2 个表达式的相等性。但是,我没想到平等是不及物的(例如n == s1, s1 == s2
,但是n != s2
。)
此外,floor
尽管保留了 40 个有效数字,但似乎在整数部分上失去了精度。
Prelude> s1
5.70597955061867e39
Prelude> s2
5705979550618669899723442048678773129216
在测试减法时,这种损失的精度变得很明显:
Prelude> (fromIntegral n) - s1
0.0
Prelude> (fromIntegral n) - (fromIntegral s2)
546585136809863902244767
为什么会floor
失去精度,这如何违反平等的传递性(如果有的话)?
floor . sqrt
在不损失精度的情况下,最好的计算方法是什么?