Hi,

On Sat, Oct 15, 2011 at 1:34 PM, Derek Homeier
<de...@astro.physik.uni-goettingen.de> wrote:
> On 15.10.2011, at 9:42PM, Aronne Merrelli wrote:
>
>>
>> On Sat, Oct 15, 2011 at 1:12 PM, Matthew Brett <matthew.br...@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)...

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/<ipython-input-148-5cc20524867d> in <module>()
----> 1 np.float128(0) + 2**63

TypeError: unsupported operand type(s) for +: 'numpy.float128' and 'long'

In [149]: np.float128(0) - 2**63
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/mb312/<ipython-input-149-4d5064ca1f61> in <module>()
----> 1 np.float128(0) - 2**63

TypeError: unsupported operand type(s) for -: 'numpy.float128' and 'long'

In [150]: np.float128(0) * 2**63
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/mb312/<ipython-input-150-ee0123db30da> in <module>()
----> 1 np.float128(0) * 2**63

TypeError: unsupported operand type(s) for *: 'numpy.float128' and 'long'

In [151]: np.float128(0) / 2**63
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/mb312/<ipython-input-151-cbbf8ad624fa> in <module>()
----> 1 np.float128(0) / 2**63

TypeError: unsupported operand type(s) for /: 'numpy.float128' and 'long'

Thanks for the feedback,

Best,

Matthew
_______________________________________________
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion

Reply via email to