我只是在挖掘Haskell,我开始尝试计算文本中两个单词的Phi-Coefficient。但是,我遇到了一些我无法解释的非常奇怪的行为。
在删除所有内容后,我最终使用此代码重现问题:
let sumTup = (sumTuples∘concat) frequencyLists
let sumFixTup = (138, 136, 17, 204)
putStrLn (show ((138, 136, 17, 204) == sumTup))
putStrLn (show (phi sumTup))
putStrLn (show (phi sumFixTup))
输出:
True
NaN
0.4574206676616167
因此虽然sumTup
和sumFixTup
显示相同,但传递给phi
时其行为会有所不同。
phi
的定义是:
phi (a, b, c, d) =
let dividend = fromIntegral(a * d - b * c)
divisor = sqrt(fromIntegral((a + b) * (c + d) * (a + c) * (b + d)))
in dividend / divisor
答案 0 :(得分:8)
这可能是整数溢出的情况。传递到除数中fromIntegral
的值为3191195800,大于32位有符号Int可以容纳的值。
在ghci(或您正在使用的任何内容)中,使用
:t sumTup
:t sumFixTup
查看这些变量的类型。我猜你会发现sumTup
是(Int, Int, Int, Int)
(溢出)而sumFixTup
是(Integer, Integer, Integer, Integer)
(不会溢出)。
编辑:第二个想法,Ints的元组不能等于整数元组。即便如此,我认为ghci会将sumFixTup
的类型修改为整数元组,而sumTup
可能有(Num a) => (a, a, a, a)
或(Integral a) => (a, a, a, a)
形式的类型,取决于定义它的功能。
然后Ghci会将它们转换为整数以与sumFixTup
进行比较,但在计算phi
中的除数时可能会将它们转换为Ints,从而导致溢出。
另一个编辑:KennyTM,你是对的一半:
Prelude> :t (1,2,3,4)
(1,2,3,4) :: (Num t, Num t1, Num t2, Num t3) => (t, t1, t2, t3)
Prelude> let tup = (1,2,3,4)
Prelude> :t tup
tup :: (Integer, Integer, Integer, Integer)
所以对于问题中给出的例子:
putStrLn (show ((138, 136, 17, 204) == sumTup))
文字(138, 136, 17, 204)
被推断为匹配Int
的{{1}}元组,并且它们相等。
sumTup
putStrLn (show (phi sumTup))
由sumTup
组成,导致溢出,如上所述。
Int
putStrLn (show (phi sumFixTup))
由sumFixTup
组成,给出了正确的结果。请注意,Integer
和sumTup
从未直接进行过比较,因此我之前的编辑是基于误读。</ p>