-
-
Notifications
You must be signed in to change notification settings - Fork 12k
Description
Describe the issue:
Conversion from a Python int to an np.float32 value does not appear to be correctly rounded, and does not always match the equivalent conversion from np.int64 to np.float32.
I'm a bit hesitant to call this a bug rather than a feature request, since I'm not aware of anywhere where it's specified that int to np.float32 conversions should be correctly rounded. But whether bug or not, correct rounding seems like a desirable property here, and consistency between int and np.int64 also seems desirable.
In IEEE 754 binary32 floating-point, 2**54 - 2**30 and 2**54 are both exactly representable, and are neighboring floating-point values. The halfway point between them is 2**54 - 2**29. Under correct rounding (ties-to-even, as usual), integers n in the interval [2**54 - 2**29, 2**54) should round up to 2**54 when converted to np.float32, while integers in (2**54-2**30, 2**54-2**29) should round down to 2**54 - 2**30. In particular, 2**54 - 2**29 - 1 should round down, but as the code example below shows, it rounds up.
In contrast, the exact same input value represented as an int64 instead of an int rounds down (as expected).
I haven't looked at the implementation, but my strong suspicion is that there's a double rounding going on here: that the incoming int is converted first to float64, and then to float32.
Reproduce the code example:
>>> import numpy as np
>>> np.float32(2**54 - 2**29 - 1) == 2**54 - 2**30 # expect True, get False
False
>>> np.float32(np.int64(2**54 - 2**29 - 1)) == 2**54 - 2**30 # ok: expect True, get True
TrueSecond example, to emphasise the unexpected difference in behaviour between int and np.int64:
>>> import numpy as np
>>> x = 2**54 - 2**29 - 1
>>> y = np.int64(x)
>>> x == y
True
>>> np.float32(x) == np.float32(y) # expect True, get False
FalseError message:
No response
NumPy/Python version information:
>>> import sys, numpy
>>> print(numpy.__version__)
1.21.4
>>> print(sys.version)
3.9.9 (main, Nov 16 2021, 07:23:17)
[Clang 10.0.1 (clang-1001.0.46.4)]