float2Int
似乎在2^^62
和2^^63
之间的某处溢出(我在使用GHC 7.6.1的intel iMac上尝试过它)。我在尝试检查maxBound
Int
时发现了这个问题。 float2Int
在GHC中作为primop float2Int#
实现。
我的intel mac上的GHCi提示输出低于 - maxBound::Int
是2^^63
。我还尝试将2^^63
转换为Float
,然后稍微减少值以查看溢出是否消失(如果有的话,考虑到小的舍入错误)。它没有:
λ: maxBound :: Int
9223372036854775807
λ: GHC.Float.float2Int $ 2^^63 -- overflows
-9223372036854775808
λ: GHC.Float.float2Int $ (9223372036854775807::Float) -- now try actual value of 2^^63
-9223372036854775808
λ: GHC.Float.float2Int $ (9223372036854000000::Float) -- reduce it a bit
-9223372036854775808
λ: minBound :: Int -- overflow value is same as minBound::Int
-9223372036854775808
λ: GHC.Float.float2Int $ 2^^62 + 2^^61 -- works fine here
6917529027641081856
64位Int边界上的溢出是否是预期的行为?它似乎在2^^62
之前正常工作,并在2^^62
和2^^63
之间的某处溢出。我查了GHC trac,看看是否有任何报告错误,并没有发现任何错误。关于这个,我没有找到关于SO的任何帖子。
答案 0 :(得分:8)
这是正确的行为。首先,让我们澄清一个小细节:
maxBound :: Int在我的intel mac上是2 ^^ 63
不,它应该是(2^63) - 1
。减去一个是非常重要的,因此float2Int (2^^63)
应该溢出。
现在你的削减怎么样?考虑一下:
Prelude GHC.Float.RealFracMethods> let a = 9223372036854775807::Float
Prelude GHC.Float.RealFracMethods> let b = 9223372036854000000::Float
Prelude GHC.Float.RealFracMethods> a == b
True
浮点数是近似值,并且您的减少不会导致浮点数发生重大变化。到目前为止的输入都等于2^63
。
最后,
> 2^^62 + 2^^61 < (2^^63 :: Float)
True
在上一次测试中,您发现了一个数字,当转换为Float时,表示为小于2^63
的数字,因此在64位Int
的范围内,从而产生您的预期值