Re: [Numpy-discussion] Float128 integer comparison
Hi, On Sat, Oct 15, 2011 at 1:34 PM, Derek Homeier wrote: > On 15.10.2011, at 9:42PM, Aronne Merrelli wrote: > >> >> On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett >> wrote: >> Hi, >> >> Continuing the exploration of float128 - can anyone explain this behavior? >> >> >>> np.float64(9223372036854775808.0) == 9223372036854775808L >> True >> >>> np.float128(9223372036854775808.0) == 9223372036854775808L >> False >> >>> int(np.float128(9223372036854775808.0)) == 9223372036854775808L >> True >> >>> np.round(np.float128(9223372036854775808.0)) == >> >>> np.float128(9223372036854775808.0) >> True >> >> >> I know little about numpy internals, but while fiddling with this, I noticed >> a possible clue: >> >> >>> np.float128(9223372036854775808.0) == 9223372036854775808L >> False >> >>> np.float128(4611686018427387904.0) == 4611686018427387904L >> True >> >>> np.float128(9223372036854775808.0) - 9223372036854775808L >> Traceback (most recent call last): >> File "", line 1, in >> TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long' >> >>> np.float128(4611686018427387904.0) - 4611686018427387904L >> 0.0 >> >> >> My speculation - 9223372036854775808L is the first integer that is too big >> to fit into a signed 64 bit integer. Python is OK with this but that means >> it must be containing that value in some more complicated object. Since you >> don't get the type error between float64() and long: >> >> >>> np.float64(9223372036854775808.0) - 9223372036854775808L >> 0.0 >> >> Maybe there are some unimplemented pieces in numpy for dealing with >> operations between float128 and python "arbitrary longs"? I could see the == >> test just producing false in that case, because it defaults back to some >> object equality test which isn't actually looking at the numbers. > > That seems to make sense, since even upcasting from a np.float64 still lets > the test fail: np.float128(np.float64(9223372036854775808.0)) == 9223372036854775808L > False > while np.float128(9223372036854775808.0) == np.uint64(9223372036854775808L) > True > > and np.float128(9223372036854775809) == np.uint64(9223372036854775809L) > False np.float128(np.uint(9223372036854775809L) == np.uint64(9223372036854775809L) > True > > Showing again that the normal casting to, or reading in of, a np.float128 > internally inevitably > calls the python float(), as already suggested in one of the parallel threads > (I think this > also came up with some of the tests for precision) - leading to different > results than > when you can convert from a np.int64 - this makes the outcome look even > weirder: > np.float128(9223372036854775807.0) - np.float128(np.int64(9223372036854775807)) > 1.0 np.float128(9223372036854775296.0) - np.float128(np.int64(9223372036854775807)) > 1.0 np.float128(9223372036854775295.0) - np.float128(np.int64(9223372036854775807)) > -1023.0 np.float128(np.int64(9223372036854775296)) - np.float128(np.int64(9223372036854775807)) > -511.0 > > simply due to the nearest np.float64 always being equal to MAX_INT64 in the > two first cases > above (or anything in between)... Right - just for the record, I think there are four relevant problems. 1: values being cast to float128 appear to go through float64 -- In [119]: np.float128(2**54-1) Out[119]: 18014398509481984.0 In [120]: np.float128(2**54)-1 Out[120]: 18014398509481983.0 2: values being cast from float128 to int appear to go through float64 again --- In [121]: int(np.float128(2**54-1)) Out[121]: 18014398509481984 http://projects.scipy.org/numpy/ticket/1395 3: comparison to python long ints is always unequal --- In [139]: 2**63 # 2*63 correctly represented in float128 Out[139]: 9223372036854775808L In [140]: int(np.float64(2**63)) Out[140]: 9223372036854775808L In [141]: int(np.float128(2**63)) Out[141]: 9223372036854775808L In [142]: np.float128(2**63) == 2**63 Out[142]: False In [143]: np.float128(2**63)-1 == 2**63-1 Out[143]: True In [144]: np.float128(2**63) == np.float128(2**63) Out[144]: True Probably because, as y'all are saying, numpy tries to convert to np.int64, fails, and falls back to an object array: In [145]: np.array(2**63) Out[145]: array(9223372036854775808L, dtype=object) In [146]: np.array(2**63-1) Out[146]: array(9223372036854775807L) 4 : any other operation of float128 with python long ints fails -- In [148]: np.float128(0) + 2**63 --- TypeError Traceback (most recent call last) /home/mb312/ in () > 1 np.float12
Re: [Numpy-discussion] Float128 integer comparison
On 15.10.2011, at 9:42PM, Aronne Merrelli wrote: > > On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett > wrote: > Hi, > > Continuing the exploration of float128 - can anyone explain this behavior? > > >>> np.float64(9223372036854775808.0) == 9223372036854775808L > True > >>> np.float128(9223372036854775808.0) == 9223372036854775808L > False > >>> int(np.float128(9223372036854775808.0)) == 9223372036854775808L > True > >>> np.round(np.float128(9223372036854775808.0)) == > >>> np.float128(9223372036854775808.0) > True > > > I know little about numpy internals, but while fiddling with this, I noticed > a possible clue: > > >>> np.float128(9223372036854775808.0) == 9223372036854775808L > False > >>> np.float128(4611686018427387904.0) == 4611686018427387904L > True > >>> np.float128(9223372036854775808.0) - 9223372036854775808L > Traceback (most recent call last): > File "", line 1, in > TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long' > >>> np.float128(4611686018427387904.0) - 4611686018427387904L > 0.0 > > > My speculation - 9223372036854775808L is the first integer that is too big to > fit into a signed 64 bit integer. Python is OK with this but that means it > must be containing that value in some more complicated object. Since you > don't get the type error between float64() and long: > > >>> np.float64(9223372036854775808.0) - 9223372036854775808L > 0.0 > > Maybe there are some unimplemented pieces in numpy for dealing with > operations between float128 and python "arbitrary longs"? I could see the == > test just producing false in that case, because it defaults back to some > object equality test which isn't actually looking at the numbers. That seems to make sense, since even upcasting from a np.float64 still lets the test fail: >>> np.float128(np.float64(9223372036854775808.0)) == 9223372036854775808L False while >>> np.float128(9223372036854775808.0) == np.uint64(9223372036854775808L) True and >>> np.float128(9223372036854775809) == np.uint64(9223372036854775809L) False >>> np.float128(np.uint(9223372036854775809L) == np.uint64(9223372036854775809L) True Showing again that the normal casting to, or reading in of, a np.float128 internally inevitably calls the python float(), as already suggested in one of the parallel threads (I think this also came up with some of the tests for precision) - leading to different results than when you can convert from a np.int64 - this makes the outcome look even weirder: >>> np.float128(9223372036854775807.0) - >>> np.float128(np.int64(9223372036854775807)) 1.0 >>> np.float128(9223372036854775296.0) - >>> np.float128(np.int64(9223372036854775807)) 1.0 >>> np.float128(9223372036854775295.0) - >>> np.float128(np.int64(9223372036854775807)) -1023.0 >>> np.float128(np.int64(9223372036854775296)) - >>> np.float128(np.int64(9223372036854775807)) -511.0 simply due to the nearest np.float64 always being equal to MAX_INT64 in the two first cases above (or anything in between)... Cheers, Derek ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] Float128 integer comparison
On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett wrote: > Hi, > > Continuing the exploration of float128 - can anyone explain this behavior? > > >>> np.float64(9223372036854775808.0) == 9223372036854775808L > True > >>> np.float128(9223372036854775808.0) == 9223372036854775808L > False > >>> int(np.float128(9223372036854775808.0)) == 9223372036854775808L > True > >>> np.round(np.float128(9223372036854775808.0)) == > np.float128(9223372036854775808.0) > True > > I know little about numpy internals, but while fiddling with this, I noticed a possible clue: >>> np.float128(9223372036854775808.0) == 9223372036854775808L False >>> np.float128(4611686018427387904.0) == 4611686018427387904L True >>> np.float128(9223372036854775808.0) - 9223372036854775808L Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long' >>> np.float128(4611686018427387904.0) - 4611686018427387904L 0.0 My speculation - 9223372036854775808L is the first integer that is too big to fit into a signed 64 bit integer. Python is OK with this but that means it must be containing that value in some more complicated object. Since you don't get the type error between float64() and long: >>> np.float64(9223372036854775808.0) - 9223372036854775808L 0.0 Maybe there are some unimplemented pieces in numpy for dealing with operations between float128 and python "arbitrary longs"? I could see the == test just producing false in that case, because it defaults back to some object equality test which isn't actually looking at the numbers. Aronne ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
[Numpy-discussion] Float128 integer comparison
Hi, Continuing the exploration of float128 - can anyone explain this behavior? >>> np.float64(9223372036854775808.0) == 9223372036854775808L True >>> np.float128(9223372036854775808.0) == 9223372036854775808L False >>> int(np.float128(9223372036854775808.0)) == 9223372036854775808L True >>> np.round(np.float128(9223372036854775808.0)) == >>> np.float128(9223372036854775808.0) True Thanks for any pointers, Best, Matthew ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion