$ python --version
Python 2.7.15
$ type test.py
import random
while True:
a = random.uniform(0, 1)
b = a ** 2
c = a * a
if b != c:
print "a = {}".format(a)
print "a ** 2 = {}".format(b)
print "a * a = {}".format(c)
break
$ python test.py
a = 0.145376687586
a ** 2 = 0.0211343812936
a * a = 0.0211343812936
Мне удалось воспроизвести это только на сборке Python для Windows, если быть точным: Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
.На моем Arch Linux боксе Python (Python 2.7.15 (default, May 1 2018, 20:16:04) [GCC 7.3.1 20180406] on linux2
), похоже, цикл не прерывается, указывая на то, что там сохраняется инвариант a**2 = a * a
.
Что здесь происходит?Я знаю, что поплавки IEEE сопровождаются множеством заблуждений и особенностей (например, this не отвечает на мой вопрос), но я не вижу, какая часть спецификации или какая реализация **
может допустить это.
Для устранения дублирования пометки: это, скорее всего, не напрямую математическая задача IEEE с плавающей запятой, а скорее проблема реализации оператора **
.Следовательно, это не дубликат вопросов, которые задают только вопросы с плавающей запятой, такие как точность или ассоциативность.