Bigfloat - Ошибка в точности

Я пытаюсь использовать библиотеку Bigfloat в Python 2.7.

from bigfloat import *

f1 = Context(precision=2000)

with precision(2000):  f1 = 1e-19*1e-19*9e9/((1-1e-18)*(1-1e-18))-1e-19*1e-19*9e9

with precision(100):  f2 = 1.6e-27*1.6e-27*6.6e-11/(1e-18*1e-18)

print BigFloat(f1) print f2

Python дает мне f1=0, но это не так. Я проверил это с g++, и результат 1.75e-46,

Это ошибка в моей программе? Разве нельзя рассчитать эту точность с Bigfloat? Это ошибка в библиотеке?

1 ответ

Решение

В качестве примера, вот как вы можете вычислить f1 с точностью до 256 бит, используя bigfloat библиотека.

>>> from bigfloat import BigFloat, precision
>>> with precision(256):
...     x = BigFloat('1e-19')
...     y = BigFloat('9e9')
...     z = BigFloat('1e-18')
...     f1 = x * x * y / ((1 - z) * (1 - z)) - x * x * y
... 
>>> f1
BigFloat.exact('1.800000000000000002700000000000000003600000000000000004500006811997284879750608e-46', precision=256)

Обратите внимание на использование BigFloat('1e-19'), который создает ближайший двоичный файл с плавающей точкой 10**-19 с текущей точностью (256 бит). Это отличается от BigFloat(1e-19) (без одинарных кавычек), так как есть 1e-19 это число с плавающей точкой Python, поэтому оно уже округлено до 53-битной точности.

Посмотрите на документацию для более подробной информации.

Однако, с небольшим творческим потенциалом и алгеброй, вам не нужна высокоточная библиотека. Вы можете переписать выражение для f1 как:

f1 = x * x * y * (1 / ((1 - z) * (1 - z)) - 1)

и поместив все в общий знаменатель, количество в скобках можно переписать как (2 - z) * z / ((1 - z) * (1 - z)), Таким образом, вы могли бы одинаково хорошо вычислить f1 как:

f1 = x * x * y * (2-z) * z / ((1 - z) * (1 - z))

и в этой форме вы не теряете точность, когда z очень маленький Так что теперь обычные поплавки Python достаточно хороши:

>>> x = 1e-19
>>> y = 9e9
>>> z = 1e-18
>>> f1 = x * x * y * (2 - z) * z / ((1 - z) * (1 - z))
>>> f1
1.8e-46

Если вы решите, что хотите использовать высокоточную библиотеку с плавающей точкой, я бы также порекомендовал взглянуть на библиотеку gmpy2. Он основан на той же базовой библиотеке MPFR, что и bigfloat, но лучше поддерживается.

Другие вопросы по тегам