大きな整数を定義することから始めますn
。
Prelude> let n = 5705979550618670446308578858542675373983
Prelude> n :: Integer
5705979550618670446308578858542675373983
次に、 と の動作を調べましs1
た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
, but 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
精度を落とさずに計算するための最良のアプローチは何ですか?