1

I got a very wired test for python2.7 numpy array. Please look at this code.

import numpy as np
times = np.arange(5., 85, 0.1)
print times
times = np.array(times * 10, dtype=np.int)
print times

the original times should be [5.0 ~ 84.9]. After multiply 10, it should become [50 ~ 849], but result is like this:

[ 50 51 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 ... ]
There are two 51 between 50 and 52

sccds
  • 11
  • 4
  • This is basically a floating point problem. `(times * 10)[2]` is `51.999999999999993`. If you cast it as int, it will return 51, not 52. – ayhan Aug 19 '17 at 09:06

1 Answers1

3

The problem is, that your third entry isn't exactly 52.0 but 51.999999999999993 (see Is floating point math broken?). Truncating that value therefore results in 51.

The correct way would be to first round the values. (As pointed out in Safest way to convert float to integer in python? all small enough integer numbers can be exactly expressed as a float.) You therefore have to calculate: times = np.array(np.round(times * 10), dtype=np.int)

Stephan
  • 2,028
  • 16
  • 19
  • Thank you very much! I think for multiply 10, we can use + 0.5, but how about multiply an variable, not only 10? I want to make sure the result must not same in nearby numbers if the original array not same. – sccds Aug 19 '17 at 09:29
  • Adding 0.5 works for all positive numbers, since it "converts" a truncation to a rounding operation. For example 0.999 gets 1.499, which truncated results in 1. However if the small decrease in performance is no problem using `np.round` (as in my updated answer) is the better option (and also working for negative numbers). – Stephan Aug 19 '17 at 09:40