Bigfloat - 精度错误
Bigfloat - Error in the precision
我正在尝试在 python 2.7.
中使用 Bigfloat 库
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 计算此精度吗?是lib中的错误吗?
例如,您可以使用 bigfloat
库将 f1
计算为 256 位精度。
>>> 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')
的使用,它以当前精度(256 位)创建最接近 10**-19
的二进制浮点数。这与 BigFloat(1e-19)
(没有单引号)不同,因为 1e-19
是一个 Python 浮点数,所以已经四舍五入到 53 位精度。
查看 documentation 了解更多详情。
但是,只要有一点创造力和代数知识,这里就完全不需要高精度库了。您可以将 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 库。它基于与 bigfloat 相同的底层 MPFR 库,但维护得更好。
我正在尝试在 python 2.7.
中使用 Bigfloat 库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 计算此精度吗?是lib中的错误吗?
例如,您可以使用 bigfloat
库将 f1
计算为 256 位精度。
>>> 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')
的使用,它以当前精度(256 位)创建最接近 10**-19
的二进制浮点数。这与 BigFloat(1e-19)
(没有单引号)不同,因为 1e-19
是一个 Python 浮点数,所以已经四舍五入到 53 位精度。
查看 documentation 了解更多详情。
但是,只要有一点创造力和代数知识,这里就完全不需要高精度库了。您可以将 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 库。它基于与 bigfloat 相同的底层 MPFR 库,但维护得更好。