Патч из 36 цифр в выводе на печать ('%. 70f'% (0,2 + 0,1)) - PullRequest
0 голосов
/ 01 октября 2019

Я понимаю, почему 0.1 + 0.2 дает это в Python 3:

>>> 0.1 + 0.2
0.30000000000000004

... но я не понимаю, почему существует 36-значный участок (в основном) ненулевых цифр всередина вывода, показанного ниже:

>>> print('%.70f' % (0.2 + 0.1))
0.3000000000000000444089209850062616169452667236328125000000000000000000

Я ожидаю, что будет разница между 0,1 + 0,2 и двоичным числом с плавающей запятой IEEE 754, ближайшим к 0,1 + 0,2, но я не понимаю, почему эта разницаприведет к 36-значному представлению (что соответствует примерно ~ 120 битам точности).

Я мог бы понять, имела ли ошибка гораздо меньшую (<53 бит) точность, или имела (кажущуюся) бесконечную точность, может быть из-за артефакта алгоритма оценки <code>'%.70f' % (0.2 + 0.1). Но я не могу понять ошибку, которая привела бы к 36-значному патчу, показанному выше.

1 Ответ

1 голос
/ 01 октября 2019

Реализация Python, которую вы используете, по-видимому, использует IEEE-754 binary64 для плавающей запятой. (Это часто встречается, но Python не предписывает это.)

В этом формате числа представляются в виде кратных степеней двух, где конкретная используемая степень двух зависит от величины числа. (Формат с плавающей запятой также описан другими способами, которые математически эквивалентны этому, например, использование значения и фиксированного числа дробных бит вместо целого числа, как я использую здесь. Это описание проще для объяснения встрелка.)

Для чисел около .3 используется степень двух: 2 −54 . Результат добавления .1 и .2 после округления для подгонки в формате с плавающей запятой равен 5404319552844596 раз 2 −54 или 5404319552844596/2 54 .

Это число, 5404319552844596/2 54 , в точности равно 0,3000000000000000444089209850062616169452667236328125.

...