0

Haskell を少し掘り下げて、テキスト内の 2 つの単語のファイ係数を計算することから始めました。ただし、説明できない非常に奇妙な動作に遭遇しました。

すべてを取り除いた後、問題を再現するために次のコードになりました。

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)ない) であることがわかると思います。

編集: よく考えてみると、Int のタプルを Integer のタプルと等しくすることはできません。それでも、ghci は の型を IntegersumFixTupのタプルに修正すると思いますが、おそらくorsumTupという形式の型を持ちますが、これはそれを定義する関数に依存します。(Num a) => (a, a, a, a)(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))

リテラルはto match(138, 136, 17, 204)のタプルであると推測され、それらは等しいと比較されます。IntsumTup

putStrLn (show (phi sumTup))

sumTups で構成され、Int上記のようにオーバーフローを引き起こします。

putStrLn (show (phi sumFixTup))

sumFixTups で構成されInteger、正しい結果が得られます。sumTupとが直接比較されたことがないことに注意してください。そのsumFixTupため、私の以前の編集は読み間違いに基づいていました。

于 2010-03-31T15:04:08.020 に答える