2017-03-16 7 views
1

バイナリログ(ログベース2)に基づいて計算を計算するために書いたコードで、奇妙なエラーが見つかりました。ここで、正の整数のバイナリ対数計算lbためのコードである:2の累乗で予期しない動作が発生する

lb :: Int -> Maybe Int -- Binary logarithm, rounded down 
lb 1 = Just 0 
lb x 
    | 1 < x = (+1) <$> lb (div x 2) 
    | otherwise = Nothing 
ここ

それはlb (2^31)が何らかの形で失敗したと思われるエラーは、次の注釈付きGHCiの出力

λ: lb (2^30) 
Just 30 
λ: lb (2^31) -- should be Just 31 
Nothing 
λ: 1 < 2^31 -- smoke check, lb's first guard evaluates to True 
True 
λ: lb (div (2^31) 2) == lb (2^30) -- smoke check, these should be equal 
False 
λ: div (2^31) 2 == 2^30 -- smoke check, these are indeed equal 
True 

に示されているように、あります最初のガードは、otherwiseの式につながっていますが、私はその理由を一貫して説明できません。

さらに、表現div (2^31) 2は何とかIntIntegerからlb

+1

'Int'を' Integer'に切り替えようとしましたか?私はおそらくアンダーフローの問題があると思う。そして、私はデフォルトが 'Integer'だと思いますので、3番目のラムダはうまくいくはずです... – Dair

+0

ああ、テスト値を型制約するのを忘れました。うん、それはそれを解決する必要があります。 –

答えて

4

スイッチの本体に2^30と同じものと評価されていないようです。基本的には、オーバーフローするほど大きいIntを作成しています。 Integerは任意の精度です。

(注:異なるアーキテクチャでは、数値は異なる場合があります。私のコンピュータは31の代わりに63で失敗します)。

+0

私はそれを一般的に保つためにインテグラルを使用していますが、それはうまくいきます –

関連する問題