I'm trying to use Bigfloat library in 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 gives me f1=0
, but it is not true. I tested it with g++ and the result is 1.75e-46
.
Is it an error in my program? Is it not possible to calculate this precision with Bigfloat ? Is it an error in the lib?
As an example, here's how you might compute f1
to a precision of 256 bits using the bigfloat
library.
>>> 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)
Note the use of BigFloat('1e-19')
, which is creating the closest binary float to 10**-19
at the current precision (256 bits). This is different from BigFloat(1e-19)
(without the single quotes), since there 1e-19
is a Python float, so has already been rounded to 53-bit precision.
Take a look at the documentation for more details.
However, with a bit of creativity and algebra, you don't need a high-precision library at all here. You can rewrite the expression for f1
as:
f1 = x * x * y * (1 / ((1 - z) * (1 - z)) - 1)
and by putting everything over a common denominator, the quantity in parentheses can be rewritten as (2 - z) * z / ((1 - z) * (1 - z))
. So you could equally well compute f1
as:
f1 = x * x * y * (2-z) * z / ((1 - z) * (1 - z))
and in this form, you don't lose accuracy when z
is very small. So now regular Python floats are good enough:
>>> x = 1e-19
>>> y = 9e9
>>> z = 1e-18
>>> f1 = x * x * y * (2 - z) * z / ((1 - z) * (1 - z))
>>> f1
1.8e-46
If you do decide you want to use a high-precision floating-point library, I'd also recommend looking at the gmpy2 library. It's based on the same underlying MPFR library as bigfloat, but it's better maintained.