Closed
Description
EDIT: since this issue has become somewhat of a stand-in for uint64
-problems, here's a summary pulled up from the discussion further down:
PS. Here's all the duckies in one neat row:
- open related issues (all about
uint64
breaking due to casting tofloat
, or closely related): np.left_shift and np.right_shift fail on np.uint64 scalar types (Trac #1931) #2524, uint64 modulo arithmetic broken (Trac #1940) #2533, bitwise_and with uint64 #2955, r/l shift on uint64 scalar and python int failing #4151, shift operator does not work with numpy arrays with dtype=uint64 #5668, uint64 converted silently to float64 when adding an int #5745, Cannot reliably compare uint64 values to integers? #5746, NumPy's implementation of scalar integer ** integer has very weird casting #7449, bitshift typing on unsigned operands is tedious to work with #8002, BUG: Inconsistent behaviour of return type of int64.__pow__ #8809, BUG: incorrect equality of np.int64 and np.uint64 #8851, numpy.eye raises TypeError on numpy.uint64 input #9982, Unexpected integer division/modulus result when using np.uint64 #10148, DOC: Improve the description of thedtype
parameter innumpy.array
docstring #10614,.dtype.type
class object is not preserved over some operations #11020, Invalid integer comparison #11801- open related PRs: BUG: Prevent power(uint64, int64) casting to float #8853
- closed/duplicate issues (prob. very incomplete): np.left_shift and np.right_shift fail on np.uint64 scalar types (Trac #1930) #2523, np.uint64 + int == ... np.float64 ?? #7126, uint64 is "promoted" to float64 when adding an integer #8522, Numpy uint64 added to Python int yields float #8986
- loosely related (prob. very incomplete): The epic dtype cleanup plan #2899, BUG: Inconsistent type resolution for 0d arrays #10322, Why does indexing an array after boolean comparison provide different results than doing a boolean comparison of an index? #10982, The type conversion problem of array operations #11485, WIP, NEP: add dtype design NEP - DtypeMeta, Dtype, and hierarchy #12660
There's a range of values of class np.uint64
that fail a trivial comparison test: v > v - 1
The issue is IMO that it effectively uses float-logic of some kind in the background, which is obviously neither desirable nor necessary.
Reproducing code example:
The following comparisons should all return True
:
>>> import numpy as np
>>> for v in np.logspace(50, 63.9, num=20, base=2):
... v = int(v)
... c = np.array([v], dtype='uint64').max() > v - 1
... print(c, v)
...
True 1125899906842624
True 1869506547705232
True 3104232188555715
True 5154439010814696
True 8558715940823230
False 14211365854171536
False 23597338764077220
False 39182327895891032
False 65060506809279480
False 108030067981851424
False 179379106627232000
False 297851001073046464
False 494568294537084288
False 821208581069482368
False 1363580199279397888
False 2264164065900722176
False 3759543384412024832
False 6242554005755503616
True 10365482328612339712
True 17211420807207079936
The way I encountered this, is that 'uint64'
is the default dtype for values between np.iinfo('int64').max + 1
and np.iinfo('uint64').max
(which makes sense), but leads to the following problem:
>>> v = np.iinfo('int64').max
>>> np.array([v + 1]) > v
array([ True])
>>> np.array([v + 1]).max() > v
False
>>> np.array([v + 1000]).max() == v
True
Numpy/Python version information:
Numpy version: 1.15.4
Python version: 3.6.6 (conda-forge)