Python numpy создает неожиданные результаты
Я использую функцию arange для определения итераций цикла for и получения неожиданных результатов.
i = arange(7.8,8.4,0.05)
print i
выдает следующее:
[ 7.8 7.85 7.9 7.95 8. 8.05 8.1 8.15 8.2 8.25 8.3 8.35 8.4 ]
но используя значение остановки 8.35 следующим образом
i = arange(7.8,8.35,0.05)
дает следующее
[ 7.8 7.85 7.9 7.95 8. 8.05 8.1 8.15 8.2 8.25 8.3 ]
Но я хочу, чтобы мой диапазон заканчивался на 8.35! Я знаю, что могу использовать значение остановки > 8.35 и < 8.4 для достижения моего результата, но почему это отличается и, на мой взгляд, непоследовательным?
Изменить: я использую версию 2.7
Ответы
Ответ 1
Возможно, это связано с ограничениями чисел с плавающей запятой. Из-за точности машины невозможно хранить все мыслимые значения как плавающие точки. Например:
>>> 8.4
8.4000000000000004
>>> 8.35
8.3499999999999996
Итак, 8.4 как плавающая точка немного больше фактического значения 8.4, в то время как 8.35 в качестве плавающей точки меньше, чем меньше.
Ответ 2
Я предполагаю, что вы видите эффекты округления с плавающей точкой.
numpy.arange
делает то же самое, что и python range
: он не включает "конечную точку". (например, range(0, 4, 2)
будет давать [0,2]
вместо [0,2,4]
)
Однако для шагов с плавающей точкой ошибки округления накапливаются, а иногда последнее значение фактически включает конечную точку.
Как указано в документации для arange
:
При использовании нецелого шага, такого как 0,1, результаты часто будут быть последовательным. Для этих случаев лучше использовать linspace
.
numpy.linspace
генерирует определенное количество точек между начальной и конечной точками. Кстати, он по умолчанию включает конечные точки.
Ответ 3
помощь функции arange говорит
For floating point arguments, the length of the result is
``ceil((stop - start)/step)``. Because of floating point overflow,
this rule may result in the last element of `out` being greater
than `stop`.
для python 2.7, Конверсии между числами с плавающей запятой и строками теперь правильно округлены на большинстве платформ.
в 2.7
>>> float(repr(2.3))
2.3
в 2.6
>>> float(repr(2.3))
2.2999999999999998
Ответ 4
У меня была та же проблема, и я применил свою собственную функцию для исправления этой проблемы округления с помощью numpy.arange:
import numpy as np
def my_arange(a, b, dr, decimals=6):
res = [a]
k = 1
while res[-1] < b:
tmp = round(a + k*dr,decimals)
if tmp > b:
break
res.append(tmp)
k+=1
return np.asarray(res)