Issue
Here is a minimal code example:
import numpy as np
x = np.array(1e-35, dtype=np.double)
y = int(1e19)
print( type(x/y) )
y = int(1e20)
print( type(x/y) )
On my machine in the former case it prints numpy.float64
, and in the latter case it prints float
. I imagine the specific numbers will vary on different machines, but the point is that for small ints the division preserves type, while for large ints the type is cast to a Python float. I would like to know whether this is a bug in Numpy or not, and whether there are any solutions besides manually casting everything to be a double.
It seems harmless, but when I try to write a ufunc
and the cast only happens on certain elements of an array, the return type becomes object
, and the program throws a "could not be coerced to provided output parameter" error.
Solution
The output type change because int(1e19)
can be safely casted to an np.int64
while int(1e20)
cannot fit in an np.int64
and thus cannot be safely casted (you can check that with y.bit_length()
). As a result, y
is first kept as pure-Python object (a variable-sized integer), then Python cast it to a pure-Python float object so the result is a also pure-Python float object too. This happens because Numpy try to apply its own semantics rules based on native types. When it cannot use them (due to unsafe/impossible casts), the fallback pure-Python object-based semantics is applied resulting in pure-Python objects. Still, this appear to be a known issue. You can check related issues and discuss with Numpy developers on GitHub for more information.
I think the best strategy is not to rely on this behaviour. Indeed, when a float-like value is multiplied by a huge integer, the huge integer will always be casted to a float-like value first (because of semantics rules). This cast likely introduces a loss of precision as well as the following multiplication. Thus, I think this is better to cast the huge integer yourself to keep in mind that the integer value may not be perfectly represented.
Answered By - Jérôme Richard
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.