类型转换和相等行为
Type conversion and equality behaviour
我是 Haskell 的新手,只是偶然发现了这个问题。我正在尝试找出一个解释,但我对 Haskell 类型没有足够的经验可以确定。
函数:
mystery :: Int -> Int -> Float -> Bool
mystery x y z = not ((x==y) && ((fromIntegral y) == z ))
表现得就像它看起来的那样。它基本上是检查值是否都不相等,但是从 Integral
y
进行类型转换以确保它可以与 z
进行比较
如果这是真的,那么为什么:
case1 = do
if mystery 1 1 1.00000001 -- a very small number
then putStrLn "True"
else putStrLn "False"
打印 False(即值都相等,所以 1 == 1 == 1.00000001
)而:
case2 = do
if mystery 1 1 1.0000001 -- a larger number
then putStrLn "True"
else putStrLn "False"
打印为真? (即值不都相等)
我知道这可能与精度有关,但我不明白。非常感谢任何帮助。
您的代码可以简化为:
> (1.00000001 :: Float) == 1
True
看起来 Float
根本没有足够的精度来存储 1.00000001
的最后一位,因此它被截断为普通 1
.
浮点运算通常是近似的,==
也不例外。单精度浮点数 (Float
) 很快就会用完精度,而更常用的双精度浮点数 (Double
) 精度会更高。在任何一种情况下,你的小数都会被近似地转换为二进制浮点数,然后相等测试也将是近似的。一般规则:浮点表示不是数字,它们甚至不是 Eq
class 的合法实例。如果要使用它们,需要注意它们的局限性。
在这种情况下,您需要考虑何时要考虑整数等于浮点数表示。您可能想也可能不想直接依赖内置的比较和舍入操作。
对于您必须考虑的一些细节,请查看 classic What Every Computer Scientist Should Know About Floating-Point Arithmetic,不要跳过脚注中的更正和更新。
1/10^n
无法以 base2 浮点数 (IEEE 754) 表示,因此该值可能被截断。
从语义上讲,对于整数比较,truncate
浮点值可能更准确。
mystery :: Int -> Int -> Float -> Bool
mystery x y z = not (x == y && y == truncate z)
我是 Haskell 的新手,只是偶然发现了这个问题。我正在尝试找出一个解释,但我对 Haskell 类型没有足够的经验可以确定。
函数:
mystery :: Int -> Int -> Float -> Bool
mystery x y z = not ((x==y) && ((fromIntegral y) == z ))
表现得就像它看起来的那样。它基本上是检查值是否都不相等,但是从 Integral
y
进行类型转换以确保它可以与 z
如果这是真的,那么为什么:
case1 = do
if mystery 1 1 1.00000001 -- a very small number
then putStrLn "True"
else putStrLn "False"
打印 False(即值都相等,所以 1 == 1 == 1.00000001
)而:
case2 = do
if mystery 1 1 1.0000001 -- a larger number
then putStrLn "True"
else putStrLn "False"
打印为真? (即值不都相等)
我知道这可能与精度有关,但我不明白。非常感谢任何帮助。
您的代码可以简化为:
> (1.00000001 :: Float) == 1
True
看起来 Float
根本没有足够的精度来存储 1.00000001
的最后一位,因此它被截断为普通 1
.
浮点运算通常是近似的,==
也不例外。单精度浮点数 (Float
) 很快就会用完精度,而更常用的双精度浮点数 (Double
) 精度会更高。在任何一种情况下,你的小数都会被近似地转换为二进制浮点数,然后相等测试也将是近似的。一般规则:浮点表示不是数字,它们甚至不是 Eq
class 的合法实例。如果要使用它们,需要注意它们的局限性。
在这种情况下,您需要考虑何时要考虑整数等于浮点数表示。您可能想也可能不想直接依赖内置的比较和舍入操作。
对于您必须考虑的一些细节,请查看 classic What Every Computer Scientist Should Know About Floating-Point Arithmetic,不要跳过脚注中的更正和更新。
1/10^n
无法以 base2 浮点数 (IEEE 754) 表示,因此该值可能被截断。
从语义上讲,对于整数比较,truncate
浮点值可能更准确。
mystery :: Int -> Int -> Float -> Bool
mystery x y z = not (x == y && y == truncate z)