0

我只是对 Haskell 进行了一些研究,然后我开始尝试计算文本中两个单词的 Phi 系数。但是,我遇到了一些我无法解释的非常奇怪的行为。

在剥离所有内容后,我最终得到了这段代码来重现问题:

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

因此,尽管sumTupsumFixTup显示为相等,但它们在传递给 时表现不同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
4

1 回答 1

8

这可能是整数溢出的情况。传入fromIntegral除数的值是 3191195800,它大于 32 位有符号 Int 可以容纳的值。

在 ghci (或任何你正在使用的)中,使用

:t sumTup
:t sumFixTup

查看这些变量的类型。我猜你会发现sumTup(Int, Int, Int, Int)(溢出)和sumFixTup(Integer, Integer, Integer, Integer)(不溢出)。

编辑:再想一想,整数元组不能等于整数元组。即便如此,我认为 ghci 会将 of 的类型固定sumFixTup为整数元组,而sumTup可能具有(Num a) => (a, a, a, a)or形式的类型(Integral a) => (a, a, a, a),这取决于定义它的函数。

然后 Ghci 会将它们转换为整数与 比较sumFixTup,但在计算除数时可能会将它们转换为整数phi,导致溢出。


另一个编辑: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匹配的元组sumTup,它们比较相等。

putStrLn (show (phi sumTup))

sumTupInts 组成,如上所述导致溢出。

putStrLn (show (phi sumFixTup))

sumFixTupIntegers 组成,给出正确的结果。请注意,sumTup并且sumFixTup从未直接比较过,因此我之前的编辑是基于误读。

于 2010-03-31T15:04:08.020 回答