Числа с плавающей запятой точны только до определенного числа значащих цифр. Представьте, что все ваши числа, включая промежуточные результаты, точны только до двух значащих цифр, и вам нужна сумма списка [100, 1, 1, 1, 1, 1, 1]
.
- «Истинная» сумма равна 106, но это невозможно представить, поскольку нам разрешено использовать только две значащие цифры;
- "Правильный" ответ: 110 , поскольку это "истинная" сумма, округленная до 2 sf. ;
- Но если мы наивно добавим числа в последовательности, мы сначала сделаем 100 + 1 = 100 (до 2 нс), затем 100 + 1 = 100 (до 2 нс) и так далее доокончательный результат - 100 .
«Правильный» ответ может быть достигнут путем сложения чисел от наименьшего к наибольшему;1 + 1 = 2, затем 2 + 1 = 3, затем 3 + 1 = 4, затем 4 + 1 = 5, затем 5 + 1 = 6, затем 6 + 100 = 110 (до 2 нс). Тем не менее, даже это не работает в общем случае;если бы их было больше ста, то промежуточные суммы стали бы неточными. Вы можете сделать еще лучше, всегда добавляя наименьшие два оставшихся числа.
Встроенная в Python функция sum
использует наивный алгоритм, в то время как метод df['series'].sum()
использует более точный алгоритм с меньшей накопленной ошибкой округления. Из исходного кода numy , который использует pandas:
Для чисел с плавающей запятой числовая точность суммы (и np.add.reduce
), как правило, ограничивается непосредственным добавлением каждого числа по отдельности. к результату, вызывающему ошибки округления на каждом шаге. Однако часто NumPy использует численно лучший подход (частичное парное суммирование), что приводит к повышению точности во многих случаях использования. Эта улучшенная точность всегда предоставляется, когда не указывается axis
.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10. * * * * * * * * * * * * * * * * * * * * * * * * * всегда на * * * *. 1036 * В отличие от NumPy, функция Python math.fsum
использует более медленный, но более точный подход к суммированию.
Для вашего списка результат math.fsum
равен -1.484363
, что является правильнымобоснованный ответ.