[Numpy-discussion] Float128 integer comparison

Derek Homeier derek at astro.physik.uni-goettingen.de
Sat Oct 15 16:34:18 EDT 2011


On 15.10.2011, at 9:42PM, Aronne Merrelli wrote:

> 
> On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett <matthew.brett at gmail.com> 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 "<stdin>", line 1, in <module>
> 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





More information about the NumPy-Discussion mailing list