WHY? very strange...
In python, if we test np.astype() with numba
, the following will print some results as
x: [-6. -5. -4. -3. -2. -1. 0. 1. 2. 3. 4. 5.]
x-int: [-6 -5 -4 -3 -2 -1 0 1 2 3 4 5]
@numba.njit
def tt():
nn = 3
x = np.linspace(0, 4*nn-1, 4*nn)-2*nn
print(x)
print(x.astype(np.int32))
BUT, if I change the line of x to be x = np.linspace(0, 8*nn-1, 8*nn)-4*nn
, the result will be strange as
x: [-12. -11. -10. -9. -8. -7. -6. -5. -4. -3. -2. -1. 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.]
x-int: [-12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 0 2 3 4 5 6 7 8 9 10 11]
There are two 0
in x-int? why?
tl;dr: This is a reported bug of Numba.
The issue come from a slightly inaccuracy in the Numba linspace
function related to floating-point rounding. Here is an example to highlight the issue:
def tt_classic():
nn = 3
return np.linspace(0, 8*nn-1, 8*nn)-4*nn
@numba.njit
def tt_numba():
nn = 3
return np.linspace(0, 8*nn-1, 8*nn)-4*nn
print(tt_classic()[13])
print(tt_numba()[13])
Here is the result:
1.0
0.9999999999999982
As you can see, the Numba implementation does not return a exact value. While this problem cannot be avoided for big values, it can be considered as a bug for such small value since they can be represented exactly (without any loss of precision) on any IEEE-754 platform.
As a result, the cast will then truncate the floating point number 0.9999999999999982 to 0 (and not to the nearest integer). If you want a safe conversion (ie. workaround), you can explicitly tell Numpy/Numba to do it. Here is an example:
@numba.njit
def tt():
nn = 3
x = np.linspace(0, 4*nn-1, 4*nn)-2*nn
np.round(x, 0, x)
print(x)
print(x.astype(np.int32))
This bug as been reported on the Numba bug tracker here. You may also be interested in this related Numba issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With