0
votes

float2Int seems to overflow somewhere between 2^^62 and 2^^63 for 64-bit machines (I tried it on intel iMac with GHC 7.6.1). I just noticed this issue when trying to check the maxBound for Int. float2Int is implemented as a primop float2Int# in GHC.

GHCi Prompt output is below - maxBound::Int is 2^^63 on my intel mac. I also tried casting 2^^63 to Float, and then reducing the values a bit to see if the overflow goes away (to account for small rounding errors if any). It doesn't:

λ: 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

Is this overflow on 64-bit Int boundary an expected behavior? It seems to work fine until 2^^62, and overflows somewhere between 2^^62 and 2^^63. I looked up GHC trac to see if there were any reported bugs, and didn't find any. I didn't find any posts on SO either about this one.

1
<irrelevant>A number theorist once said to me that people feel that big numbers are like small numbers, only bigger, but that they really really aren't.</irrelevant> - AndrewC

1 Answers

8
votes

This is all correct behavior. First, lets clear up a minor detail:

maxBound::Int is 2^^63 on my intel mac

No, it should be (2^63) - 1. That minus one is very important so float2Int (2^^63) should overflow.

Now how about your reductions? Consider this:

Prelude GHC.Float.RealFracMethods> let a = 9223372036854775807::Float
Prelude GHC.Float.RealFracMethods> let b = 9223372036854000000::Float
Prelude GHC.Float.RealFracMethods> a == b
True

Floats are approximations and your reduction has not cause a material change in the Float. The inputs so far are all equal to 2^63.

Finally,

> 2^^62 + 2^^61 < (2^^63 :: Float)
True

With your last test you found a number that, when cast as a Float, is represented as something less than 2^63, thus within the range of a 64 bit Int and resulting in your expected value.