sum() теперь использует специальный алгоритм для сложения чисел с плавающей точкой с минимальной потерей точности (прочитать про алгоритм можно на вики).Раньше было как, складываешь 10 чиселок, где в результате ожидаешь получить 1, но получаешь что-то немного другое:
>>> sum([0.1] * 10)И ладно бы оно просто всегда ошибалось одинаково, дак ведь погрешность ещё и зависит от порядка, в котором складывать числа:
0.9999999999999999
>>> sum([0.1] * 5 + [0.05] * 10)А вы разве не знали, что сложение float'ов не коммутативно?
1.0000000000000004
>>> sum([0.05] * 10 + [0.1] * 5)
0.9999999999999999
>>> sum([0.1, 0.05, 0.05, 0.05, 0.05, 0.1, 0.1, 0.05, 0.05, 0.1, 0.05, 0.05, 0.05, 0.1, 0.05])
1.0000000000000002
Но была специальная функция
math.fsum(), которая всё делает правильно:>>> math.fsum([0.1] * 10)Дак вот в 3.12 встроенная функция
1.0
>>> math.fsum([0.1] * 5 + [0.05] * 10)
1.0
>>> math.fsum([0.05] * 10 + [0.1] * 5)
1.0
sum() даёт такие же результаты, как math.fsum(). По крайней мере, я не смог найти примера, где они дали бы разный результат. Кроме того, по моим замерам, sum() работает ещё и раза в полтора быстрее math.fsum():>>> timeit.timeit("sum([0.05] * 10 + [0.1] * 5)")
0.26875441599986516
>>> timeit.timeit("math.fsum([0.05] * 10 + [0.1] * 5)", setup="import math")
0.34194887499961624
Кто-нибудь понимает, зачем теперь нужна math.fsum()?