Исчерпывающая точность с плавающей точкой в (казалось бы) бесконечном цикле
У меня есть следующий скрипт Python:
x = 300000000.0
while (x < x + x):
x = x + x
print "exec: " + str(x)
print "terminated" + str(x)
Этот, казалось бы, бесконечный цикл завершается довольно быстро, если x является числом с плавающей запятой. Но если я вместо этого изменю x на 300000000, он попадет в бесконечный цикл (в моем тесте длится дольше минуты).
Я думаю, что это связано с тем, что он исчерпывает точность числа с плавающей запятой, которое может быть представлено в памяти. Может кто-нибудь дать более подробное объяснение, почему это так?
3 ответа
- Когда вы инициализируете
x
в300000000
целая математика используется во всей программе. - Когда вы инициализируете
x
в300000000.0
вместо этого используется математика с плавающей точкой.
В Python целые числа могут расти как угодно большие. (Точнее, они ограничены доступной памятью.) Это означает, что целочисленная версия вашей программы требует очень много времени для завершения.
Самый большой float
около 1.8e308
, Требуется около 1000 итераций версии цикла с плавающей запятой, чтобы превысить это значение, и в этот момент x
получает положительную бесконечность, и программа завершается.
Это потому, что происходит переполнение с плавающей точкой. В этом случае, согласно IEEE754, x
примет значение положительной бесконечности, которая по определению не меньше чем что-либо еще:
>>> x = float("inf")
>>> x
inf
>>> x + x
inf
>>> x < x + x
False
x
удваивается после каждого шага. Конечное число x
никогда не бывает равным 2 * x
, Но как только вы превысите максимальный показатель вашего типа с плавающей запятой, удваивается x
в +infinity
, А также +infinity = 2*+infinity
, Таким образом, цикл заканчивается в этой точке.