Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy integer division sometimes yields wrong results when casted

What is the reason those two divisions give different results? I am very confused because with some numbers it gives the same results and with some it doesn't.

>>> import numpy as np
>>> a, b = np.array([844]), np.array([8186])
>>> a.dtype, b.dtype
(dtype('int32'), dtype('int32'))
>>> np.true_divide(a, b, dtype=np.float32)
array([ 0.10310286], dtype=float32)
>>> np.true_divide(a, b, dtype=np.float64)
array([-12.66666667]) # different result
>>> np.true_divide(a, b, dtype=np.float32).astype(np.float64)
array([ 0.10310286])

>>> a, b = np.array([1]), np.array([2])
>>> np.true_divide(a, b, dtype=np.float32)
array([ 0.5], dtype=float32)
>>> np.true_divide(a, b, dtype=np.float64)
array([ 0.5]) # same results

Tested on windows x64, python 3.5 and 3.6 x64, numpy 1.13.1.

EDIT: This was a numpy bug which has since been fixed (https://github.com/numpy/numpy/pull/9469).

like image 902
C. Yduqoli Avatar asked Jul 24 '17 10:07

C. Yduqoli


People also ask

How do you force an integer to divide in Python?

In Python 3. x, slash operator ("/") does true division for all types including integers, and therefore, e.g. 3/2==1.5.

What is the difference between division and integer division?

Java does integer division, which basically is the same as regular real division, but you throw away the remainder (or fraction). Thus, 7 / 3 is 2 with a remainder of 1. Throw away the remainder, and the result is 2. Integer division can come in very handy.

What is the difference between floating point division and integer division in Python?

The division function in Python has two variations: Float division: gives a decimal answer. Integer division: gives the answer in whole numbers (the division result is rounded to the nearest whole number).

How do you return an integer after division in Python?

Use the floor division operator // to return an integer from integer division, e.g. result_1 = 30 // 6 . The floor division operator will always return an integer and is like using mathematical division with the floor() function applied to the result.


1 Answers

This is a bug in numpy. Although this was supposedly fixed in 2015 it looks like it is still causing problems.

When resolving the type signature fails because of the forced cast, true_divide casts the input to int8:

>>> np.int8(844) / np.int8(8186)
-12.666667

>>> np.true_divide(844, 8186, dtype=np.float64)
-12.666666666666666

You get the correct result only for numbers between -128 and 127 because that is the range available in int8.

As a workaround you can specify the complete signature instead of only the return type:

>>> np.true_divide(844, 8186, signature='ii->d')  # int32, int32 -> float64
0.10310285853896897

>>> np.true_divide(844, 8186, signature=(np.int32, np.int32, np.float64))
0.10310285853896897
like image 60
MB-F Avatar answered Oct 04 '22 14:10

MB-F