Haskell Int64不一致?

Haskell Int64不一致?,haskell,precision,biginteger,Haskell,Precision,Biginteger,我正在尝试解决问题2的补充抱歉,它需要登录,但任何人都可以登录FB/谷歌帐户。简言之,问题是计算给定范围[a,B]内所有数字的2的补码表示中出现的1的数量,其中a和B的绝对值在32位限制231内。我知道我的算法是正确的,它在较大的绝对值中是对数的,因为我已经用另一种语言解决了这个问题 我正在我的机器上测试下面的代码,它给出了完全正确的结果。当它在Amazon服务器上运行时,它给出了一些错误的答案,显然是溢出,还有一些堆栈溢出。这不是逻辑中的错误,因为我在机器上用相同的测试输入测试相同的代码,得到

我正在尝试解决问题2的补充抱歉,它需要登录,但任何人都可以登录FB/谷歌帐户。简言之,问题是计算给定范围[a,B]内所有数字的2的补码表示中出现的1的数量,其中a和B的绝对值在32位限制231内。我知道我的算法是正确的,它在较大的绝对值中是对数的,因为我已经用另一种语言解决了这个问题

我正在我的机器上测试下面的代码,它给出了完全正确的结果。当它在Amazon服务器上运行时,它给出了一些错误的答案,显然是溢出,还有一些堆栈溢出。这不是逻辑中的错误,因为我在机器上用相同的测试输入测试相同的代码,得到不同的结果。例如,对于范围[-1548535525662630637],我在我的机器上得到35782216444,而根据测试,我的结果是一些负溢出值

我能想到的唯一问题是,可能我没有正确使用Int64,或者我对它的操作有错误的假设


感谢您的帮助。代码是。

堆栈溢出是逻辑中的一个错误

countOnes !a !b | a == b = countOnes' a

countOnes' :: Int64 -> Integer
countOnes' !0 = 0
countOnes' !a = (fromIntegral (a .&. 1)) + (countOnes' (a `shiftR` 1))
无论何时使用负参数调用countone,都会得到一个非终止计算,因为shiftR是一个算术移位,而不是逻辑移位,所以总是以1位移位,永远不会达到0。 但即使使用逻辑移位,对于负参数,也会得到一个32太大的结果,因为前32位都是1

解决方案:在调用countone'之前屏蔽掉不感兴趣的位

在Countone有一些多余的守卫

因为服务器有一个32位GHC,而您有一个64位GHC。移位距离/位宽度m是一个Int,因为它被用作移位距离,所以必须是

所以

m * (1 `shiftL` (m-1))
也是一个Int。对于m>=28,溢出32位整数

解决方案:删除一个$


那么移位的1是一个整数,因此没有溢出。

堆栈溢出是逻辑中的一个错误

countOnes !a !b | a == b = countOnes' a

countOnes' :: Int64 -> Integer
countOnes' !0 = 0
countOnes' !a = (fromIntegral (a .&. 1)) + (countOnes' (a `shiftR` 1))
无论何时使用负参数调用countone,都会得到一个非终止计算,因为shiftR是一个算术移位,而不是逻辑移位,所以总是以1位移位,永远不会达到0。 但即使使用逻辑移位,对于负参数,也会得到一个32太大的结果,因为前32位都是1

解决方案:在调用countone'之前屏蔽掉不感兴趣的位

在Countone有一些多余的守卫

因为服务器有一个32位GHC,而您有一个64位GHC。移位距离/位宽度m是一个Int,因为它被用作移位距离,所以必须是

所以

m * (1 `shiftL` (m-1))
也是一个Int。对于m>=28,溢出32位整数

解决方案:删除一个$


那么移位的1是一个整数,因此没有溢出。

如果n>=2^62,您的getLog将严重失败。值得一提的是,readLineInt只是一个整数。@ehird非常感谢:-@DanielFischer是的,但是n永远不会超过2^31。为什么使用Int64而不是Word64?后者是一个无符号值,因此您不会遇到逻辑移位与算术移位的问题。如果n>=2^62,您的getLog将严重失败。值得一提的是,readLineInt只是一个值。@ehird非常感谢:-@DanielFischer是的,但是n永远不会超过2^31。为什么使用Int64而不是Word64?后者是一个无符号值,因此您不会遇到逻辑移位与算术移位的问题。实际上,Int不是32位。Haskell报告只能保证它至少是30位,从技术上讲,这是可能的。但我敢打赌亚马逊服务器上运行着GHC,所以Int是32位或64位。我不确定其他的实现,但我想我已经听说过它们中是否有具有其他位长度的Int。实际上,Int不是32位的。Haskell报告只能保证它至少是30位,从技术上讲,这是可能的。但我敢打赌亚马逊服务器上运行着GHC,所以Int是32位或64位。我不确定其他的实现,但我想我已经听说过它们中是否有具有其他位长度的int。
m * (1 `shiftL` (m-1))
range = fromIntegral m * (1 `shiftL` (m - 1))