float64 / int comparison different from float / int comparison
Hi, I just ran into this confusing difference between np.float and np.float64: In [8]: np.float(2**63) == 2**63 Out[8]: True In [9]: np.float(2**63) > 2**63-1 Out[9]: True In [10]: np.float64(2**63) == 2**63 Out[10]: True In [11]: np.float64(2**63) > 2**63-1 Out[11]: False In [16]: np.float64(2**63-1) == np.float(2**63-1) Out[16]: True I believe values above 2*52 are all represented as integers in float64. http://matthew-brett.github.com/pydagogue/floating_point.html Is this this int64 issue that came up earlier in float128 comparison? Why the difference between np.float and np.float64? Thanks for any insight, Matthew
On Mon, Oct 31, 2011 at 11:23 AM, Matthew Brett
In [8]: np.float(2**63) == 2**63 Out[8]: True
In [9]: np.float(2**63) > 2**63-1 Out[9]: True
In [10]: np.float64(2**63) == 2**63 Out[10]: True
In [11]: np.float64(2**63) > 2**63-1 Out[11]: False
In [16]: np.float64(2**63-1) == np.float(2**63-1) Out[16]: True
Interesting. Turns out that np.float(x) returns a Python float object. If you change the experiment to only use numpy array scalars, things are more consistent: In [36]: np.array(2**63, dtype=np.float) > 2**63 - 1 Out[36]: False In [37]: np.array(2**63, dtype=np.float32) > 2**63 - 1 Out[37]: False In [38]: np.array(2**63, dtype=np.float64) > 2**63 - 1 Regards Stéfan
Hi,
2011/10/31 Stéfan van der Walt
On Mon, Oct 31, 2011 at 11:23 AM, Matthew Brett
wrote: In [8]: np.float(2**63) == 2**63 Out[8]: True
In [9]: np.float(2**63) > 2**63-1 Out[9]: True
In [10]: np.float64(2**63) == 2**63 Out[10]: True
In [11]: np.float64(2**63) > 2**63-1 Out[11]: False
In [16]: np.float64(2**63-1) == np.float(2**63-1) Out[16]: True
Interesting. Turns out that np.float(x) returns a Python float object. If you change the experiment to only use numpy array scalars, things are more consistent:
In [36]: np.array(2**63, dtype=np.float) > 2**63 - 1 Out[36]: False
In [37]: np.array(2**63, dtype=np.float32) > 2**63 - 1 Out[37]: False
In [38]: np.array(2**63, dtype=np.float64) > 2**63 - 1
Oh, dear, I'm suffering now: In [11]: res = np.array((2**31,), dtype=np.float32) In [12]: res > 2**31-1 Out[12]: array([False], dtype=bool) OK - that's what I was expecting from the above, but now: In [13]: res[0] > 2**31-1 Out[13]: True In [14]: res[0].dtype Out[14]: dtype('float32') Sorry, maybe I'm not thinking straight, but I'm confused... See you, Matthew
On Mon, Oct 31, 2011 at 6:25 PM, Matthew Brett
Oh, dear, I'm suffering now:
In [11]: res = np.array((2**31,), dtype=np.float32)
In [12]: res > 2**31-1 Out[12]: array([False], dtype=bool)
OK - that's what I was expecting from the above, but now:
In [13]: res[0] > 2**31-1 Out[13]: True
In [14]: res[0].dtype Out[14]: dtype('float32')
I'm seeing: In [7]: res = np.array((2**31,), dtype=np.float32) In [9]: res > (2**31-1) Out[9]: array([ True], dtype=bool) In [10]: res[0] Out[10]: 2.1474836e+09 In [11]: res[0] > (2**31-1) Out[11]: True Your result seems very strange, because the numpy scalars should perform exactly the same inside and outside an array. Stéfan
On 10/31/11 6:38 PM, Stéfan van der Walt wrote:
On Mon, Oct 31, 2011 at 6:25 PM, Matthew Brett
wrote: Oh, dear, I'm suffering now:
In [12]: res> 2**31-1 Out[12]: array([False], dtype=bool)
I'm seeing: ...
Your result seems very strange, because the numpy scalars should perform exactly the same inside and outside an array.
I get what Stéfan gets: In [32]: res = np.array((2**31,), dtype=np.float32) In [33]: res > 2**31-1 Out[33]: array([ True], dtype=bool) In [34]: res[0] > 2**31-1 Out[34]: True In [35]: res[0].dtype Out[35]: dtype('float32') In [36]: np.__version__ Out[36]: '1.6.1' (OS-X, Intel, Python2.7) Something is very odd with your build! -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov
Hi,
On Tue, Nov 1, 2011 at 8:39 AM, Chris.Barker
On 10/31/11 6:38 PM, Stéfan van der Walt wrote:
On Mon, Oct 31, 2011 at 6:25 PM, Matthew Brett
wrote: Oh, dear, I'm suffering now:
In [12]: res> 2**31-1 Out[12]: array([False], dtype=bool)
I'm seeing: ...
Your result seems very strange, because the numpy scalars should perform exactly the same inside and outside an array.
I get what Stéfan gets:
In [32]: res = np.array((2**31,), dtype=np.float32)
In [33]: res > 2**31-1 Out[33]: array([ True], dtype=bool)
In [34]: res[0] > 2**31-1 Out[34]: True
In [35]: res[0].dtype Out[35]: dtype('float32')
In [36]: np.__version__ Out[36]: '1.6.1'
(OS-X, Intel, Python2.7)
Something is very odd with your build!
Well - numpy 1.4.1 on Debian squeeze. I get the same as you with current numpy trunk. Stefan and I explored the issue a bit further and concluded that, in numpy trunk, the current behavior is explicable by upcasting to float64 during the comparison: In [86]: np.array(2**63, dtype=np.float) > 2**63 - 1 Out[86]: False In [87]: np.array(2**31, dtype=np.float) > 2**31 - 1 Out[87]: True because 2**31 and 2**31-1 are both exactly representable in float64, but 2**31-1 is not exactly representable in float32. Maybe this: In [88]: np.promote_types('f4', int) Out[88]: dtype('float64') tells us this information. The command is not available for numpy 1.4.1. I suppose it's possible that the upcasting rules were different in 1.4.1 and that is the cause of the different behavior. Best, Matthew
participants (3)
-
Chris.Barker
-
Matthew Brett
-
Stéfan van der Walt