Jam*_*ell 1 floating-point precision haskell
我是Haskell的新手,只是偶然发现了这个问题.我试图找出解释,但我没有足够的经验与Haskell类型确定.
功能:
mystery :: Int -> Int -> Float -> Bool
mystery x y z = not ((x==y) && ((fromIntegral y) == z ))
Run Code Online (Sandbox Code Playgroud)
表现得像它似乎会.它基本上检查值是否都不相等,但是从a进行类型转换Integral y以确保它可以与之进行比较z
如果这是真的,那么为什么:
case1 = do
if mystery 1 1 1.00000001 -- a very small number
then putStrLn "True"
else putStrLn "False"
Run Code Online (Sandbox Code Playgroud)
打印错误(即,值全部相等,所以1 == 1 == 1.00000001),而:
case2 = do
if mystery 1 1 1.0000001 -- a larger number
then putStrLn "True"
else putStrLn "False"
Run Code Online (Sandbox Code Playgroud)
打印真的吗?(即.值并非全部相等)
我知道它可能与精度有关,但我不明白.任何帮助是极大的赞赏.
浮点运算通常是近似值,==并不是该规则的例外情况之一.单精度浮点(Float)很快就会耗尽精度,而通常更有用的双精度浮点(Double)会有更多.在任何一种情况下,您的小数部分将近似转换为二进制浮点,然后相等性测试也将是近似值.一般规则:浮点表示不是数字,它们甚至不是Eq类的合法实例.如果你想使用它们,你需要注意它们的局限性.
在这种情况下,您需要考虑何时要考虑等于浮点表示的整数.您可能想要也可能不想直接依赖内置的比较和舍入操作.
有关您需要考虑的一些细节,请查看经典的每个计算机科学家应该知道的关于浮点运算的内容,并且不要跳过脚注中的更正和更新.
您的代码可以简化为:
> (1.00000001 :: Float) == 1
True
Run Code Online (Sandbox Code Playgroud)
看起来Float简单地没有足够的精度来存储最后的位1.00000001,所以它被截断为普通的1.