float и его погрешности.Питон при отображении чисел с плавающей точкой обычно успешно отбрасывает погрешность, так что мы как правило видим красивые ровные числа:
>>> 0.1
0.1
Но это число нельзя точно представить в двоичном виде, в любом случае это будет лишь аппроксимация, приближение. Так что то, что показал питон — это лишь округление, это чтобы не пугать людей. Можно посмотреть на точное значение, которое хранится внутри float, например, при помощи конвертации числа в decimal.Decimal:>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
Кстати, именно поэтому Decimal лучше создавать из строк, например, из "0.1", а не из 0.1. Потому что если вы использовали float, то Decimal сохранит его значение максимально точно, то есть тоже будет лишь аппроксимацией, и все дальнейшие вычисления будут содержать эту изначальную погрешность.Вернёмся к нашим числам с плавающей точкой.
float достаточно точно может описывать числа вокруг нуля, но чем дальше, тем сильнее падает точность аппроксимации. Например, между вот такими числами разница во float уже не представима:>>> Decimal.from_float(10.0 ** 16)
Decimal('10000000000000000')
>>> Decimal.from_float(10000000000000000.1)
Decimal('10000000000000000')
В какой-то момент float вообще перестаёт мочь представлять точно даже целые числа, например, 10 ** 22 всё ещё представимо:>>> Decimal.from_float(10.0 ** 22)
Decimal('10000000000000000000000')
А вот 10 ** 23 уже нет:>>> Decimal.from_float(10.0 ** 23)
Decimal('100000000000000008388608')
Бабах! Ошибка на восемь миллионов, но это самая точная аппроксимация, которую можно выразить на 64 битах, выделенных под число (на самом деле, мантисса числа — самая важная часть — занимает лишь 53 бита). И это мы ещё даже никаких операций над числами не делали, просто их создаём.Не знаю, есть ли на планете человек, у которого на счету лежит
10 ** 23 денег. Возможно, если конвертировать все накопления Джефа Безоса (самый богатый человек) в иранские риалы (самая дешевая валюта)... 🤔 Остаётся только надеяться, что его банк не использует float для хранения баланса.Ну, короче, вы поняли, какого порядка могут быть погрешности, если использовать
float с большими числами.Вот тут есть некоторые объяснения странностей
float: https://docs.python.org/3/tutorial/floatingpoint.html