【发布时间】:2020-01-09 13:07:25
【问题描述】:
为什么 GHCi 在下面给出错误的答案?
GHCi
λ> ((-20.24373193905347)^12)^2 - ((-20.24373193905347)^24)
4.503599627370496e15
Python3
>>> ((-20.24373193905347)**12)**2 - ((-20.24373193905347)**24)
0.0
更新 我将按如下方式实现 Haskell 的 (^) 函数。
powerXY :: Double -> Int -> Double
powerXY x 0 = 1
powerXY x y
| y < 0 = powerXY (1/x) (-y)
| otherwise =
let z = powerXY x (y `div` 2)
in if odd y then z*z*x else z*z
main = do
let x = -20.24373193905347
print $ powerXY (powerXY x 12) 2 - powerXY x 24 -- 0
print $ ((x^12)^2) - (x ^ 24) -- 4.503599627370496e15
虽然我的版本看起来并不比@WillemVanOnsem 下面提供的版本更正确,但奇怪的是,它至少为这种特殊情况给出了正确的答案。
Python 类似。
def pw(x, y):
if y < 0:
return pw(1/x, -y)
if y == 0:
return 1
z = pw(x, y//2)
if y % 2 == 1:
return z*z*x
else:
return z*z
# prints 0.0
print(pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24))
【问题讨论】:
-
这是一个尾数错误。
a^24大约是2.2437e31,因此会产生舍入误差。 -
我不明白。为什么 GHCi 会出现舍入误差?
-
这和ghci无关,只是浮点单元如何处理浮点数。
-
计算
2.243746917640863e31 - 2.2437469176408626e31,它有一个小的舍入误差,会被放大。看起来像是取消问题。 -
也许python使用不同的求幂算法,在这种情况下哪个更精确?一般来说,无论您使用哪种语言,浮点运算都会出现一些舍入误差。不过,了解这两种算法之间的差异可能会很有趣。
标签: haskell floating-point ghc ghci