Математика с плавающей точкой не обязательно ассоциативно , то есть (a+b)+c != a+(b+c)
.
Поскольку вы добавляете по разным осям, порядок операций различен, что может повлиять на конечный результат.В качестве простого примера рассмотрим матрицу, сумма которой равна 1.
a = np.array([[1e100, 1], [-1e100, 0]])
print(a.sum()) # returns 0, the incorrect result
af = np.asfortranarray(a)
print(af.sum()) # prints 1
(Интересно, что a.T.sum()
по-прежнему дает 0, как и aT = a.T; aT.sum()
, поэтому я не уверен, как именно это реализовано вбэкэнд)
В порядке C используется последовательность операций (слева направо) 1e100 + 1 + (-1e100) + 0
, тогда как в порядке Фортрана используется 1e100 + (-1e100) + 1 + 0
.Проблема в том, что (1e100+1) == 1e100
, потому что поплавки не обладают достаточной точностью, чтобы представить эту небольшую разницу, поэтому 1
теряется.
Как правило, не выполняйте тестирование на равенство для чисел с плавающей запятой, вместо этого сравните, используя маленький эпсилон (if abs(float1 - float2) < 0.00001
или np.isclose
).Если вам нужна произвольная точность с плавающей точкой, используйте библиотеку Decimal
или представление с фиксированной запятой и int
s.