2017-03-16 36 views
1

我发现了一些基于二进制对数(log base 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 

以下是错误,如下面的注释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 

似乎lb (2^31)不知何故发生故障第一个后卫,通向otherwise表达式,但我能找到没有一致的解释为什么。

此外,它似乎表达div (2^31) 2由于某种原因没有计算到同样的事情在2^30lb

+1

您是否尝试将'Int'切换为'Integer'?我认为这可能是一个下溢问题。我认为默认是'Integer',所以第三个lambda应该可以工作... – Dair

+0

啊,我忘了键入约束测试值。是的,那应该解决它。 –

回答

4

交换机的身体IntInteger。基本上,你正在创建一个很大的Int,它溢出。 Integer是任意精度。 (注意:在不同的体系结构中,数字可能有所不同,我的电脑在63而不是31)失败。

+0

我使用Integral来保持它的一般性,但是效果很好 –