2

I have a Numpy array that I obtained by multiplying a Numpy array with a float.

a = np.array([3, 5, 7, 9]) * 0.1

The resulting numbers are precise without any rounding.

>>> a
array([0.3 0.5 0.7 0.9])

However, if I turn my array into a list with a.tolist(), there are entries like 0.30000000000000004 in my list instead of 0.3.

>>> a.tolist()
[0.30000000000000004, 0.5, 0.7000000000000001, 0.9]

My question is, how can I avoid this, and if someone knows, out of pure interest, why is this happening. Thank you very much for your help.

Troll
  • 1,895
  • 3
  • 15
  • 34
Maximilian
  • 43
  • 4
  • Following excerpt from the Numpy documentation might give an idea about why it happens: [Data items are converted to the nearest compatible builtin Python type](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.tolist.html). Have you tried using list() instead? – Bedir Yilmaz Nov 03 '21 at 11:58
  • 1
    @BedirYilmaz `list(a)` also gives the messy float result as I have tried it. – Troll Nov 03 '21 at 12:09
  • 1
    it's a display issue, not a conversion one. – hpaulj Nov 03 '21 at 12:14
  • as hpaulj commented this has nothing to do with `tolist`, as you can check by `with np.printoptions(precision=20):` `print(np.array([3, 5, 7, 9]) * 0.1)` – Stef Nov 03 '21 at 12:57

2 Answers2

1

This is not a problem with Numpy. Instead, this is a well-known problem with floating-point values in Python and in other languages as well.

You can try this in the Python terminal.

>>> 3 * 0.1
0.30000000000000004

However, here is the difference.

The difference here is how Numpy and Python represent these values.

When you print a Numpy array, it passes the array through np.array_repr and returns a string representation of the array.

Notice the parameter precision. By default, it is set to numpy.get_printoptions()['precision'] or 8.

>>> np.get_printoptions()['precision']
8

Which is way before the precision 17 of 0.30000000000000004. Therefore, the result that we see is rounded to 0.3.

Let's try out some more with the precision settings.

>>> a = np.array([3, 5, 7, 9]) * 0.1

precision=17

>>> print(np.array_repr(a, precision=17))
array([0.30000000000000004, 0.5, 0.7000000000000001, 0.9])

precision=16

>>> print(np.array_repr(a, precision=16))
arrayarray([0.3, 0.5, 0.7000000000000001, 0.9])

precision=15

>>> print(np.array_repr(a, precision=15))
array([0.3, 0.5, 0.7, 0.9])

When you convert the Numpy array into a list, because lists do not have the precision feature when it comes to representing the values, the float values in lists are displayed as they are.

If you want the values to look the same when converting into a list, at least round them to the eighth decimal place.

>>> print(list(np.round(a, 8)))
[0.3, 0.5, 0.7, 0.9]
Troll
  • 1,895
  • 3
  • 15
  • 34
0

This issue comes with floating points in general (do 3 * .1 in your Python console). In your case, you can simply divide by 10 rather than multiple by .1.

a = np.array([3, 5, 7, 9]) / 10

See also: Floating Point Error Mitigation Decimal Module

Tommy A.
  • 101
  • 1
  • 8