Reputation: 497
I want to convert a numpy float to sympy and tell sympy that it is exact (e.g., it has an infinite number of 0 trailing the decimals I specify). I have tried:
from sympy import Rational, Float
num = "52.70517376823048"
num_sympy = Rational(num)
num_sympy.evalf(100)
>>> 52.70517376823048
which is not what I am after, UNLESS sympy is hiding the trailing zeros. How can I test, and is there a better way to tell sympy that a number is exact?
Upvotes: 1
Views: 59
Reputation: 14530
The code shown in the question prints lots of trailing zeros when I run it:
In [17]: from sympy import Rational, Float
...: num = "52.70517376823048"
...: num_sympy = Rational(num)
...: num_sympy.evalf(100)
Out[17]: 52.70517376823048000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Note that if you are doing something like this:
num_sympy.evalf(100)
print(num_sympy)
Then you should change it to:
num_sympy = num_sympy.evalf(100)
print(num_sympy)
Upvotes: 2
Reputation: 18866
If you have a fixed-point, rather than a floating-point value, you use the builtin Decimal
or rewrite it as a SymPy Rational
Directly from the string (likely the best/easiest)
>>> Rational("52.70517376823048").evalf(100)
52.70517376823048000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Other Examples
>>> Decimal("52.70517376823048")
Decimal('52.70517376823048')
>>> Decimal("52.70517376823048000")
Decimal('52.70517376823048000')
>>> Rational(5270517376823048, 10**14)
658814672102881/12500000000000
>>> Rational(5270517376823048, 10**14).evalf(100)
52.70517376823048000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Do watch out when worrying about small changes in the low bits of floats for XY Problems, as ideally the final result(s) you want are inside the overall accuracy available and so they can be ignored/dropped
Additionally, be aware that if you have a value that's not already an IEEE 754 float, it needs to be represented carefully (probably as a string) to avoid intermediately transforming it into one
>>> Rational(52.70517376823048).evalf(50)
52.705173768230480391139280982315540313720703125000
>>> Rational("52.70517376823048").evalf(50)
52.705173768230480000000000000000000000000000000000
See also Is floating-point math broken?
Upvotes: 2