Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sympy - Rationalize all numeric values in expression? (Like Mathematica's Rationalize[])

Is there a simple method to (attempt to) rationalize all numeric values in an expression within a given delta, much like Rationalize[] in Mathematica?

An example in Mathematica:

In[25]:= Rationalize[0.5 x^2 - 3.333333 x, 10^-4]
Out[25]= x^2/2-(10 x)/3

I see the nsimplify() function, but that seems like overkill.

like image 622
eacousineau Avatar asked Oct 08 '12 03:10

eacousineau


People also ask

How do you simplify expressions in SymPy?

With the help of sympy. simplify() method, we can simplify any mathematical expression. Parameters: expression – It is the mathematical expression which needs to be simplified.

How do you evaluate an expression in SymPy?

evalf() function and subs() function from sympy is used to evaluate algebraic expressions. Example 1: In this example, we import symbols from sympy package. An expression is created and evalf() function is used to evaluate the expression.

How can I substitute SymPy?

The subs() function in SymPy replaces all occurrences of the first parameter with the second. Substitution is the basic operations that must be performed in a mathematical expression. In this way, we can use subs() function in sympy.

How do you write a fraction in SymPy?

SymPy has Rational for working with rational numbers. A rational number is any number that can be expressed as the quotient or fraction p/q of two integers, a numerator p and a non-zero denominator q. The example works with rational numbers. The expression is in the symbolic form; we evaluate it with evalf method.


2 Answers

I don't see how nsimplify is over kill. nsimplify does exactly what you want, because you can pass it a SymPy expression, and it will rationalize the terms in the expression

>>> print nsimplify(0.5*x**2 - 3.333333*x, tolerance=0.001, rational=True)
x**2/2 - 3333333*x/1000000

(the tolerance keyword doesn't seem to work, which I guess is a bug).

like image 108
asmeurer Avatar answered Oct 11 '22 09:10

asmeurer


You can use Fraction.from_float:

>>> from fractions import Fraction
>>> Fraction.from_float(0.5)
Fraction(1, 2)

Even though it seems less smart than Mathematica:

>>> Fraction.from_float(3.33333333)
Fraction(7505999371444827, 2251799813685248)

It actually simply convert the float to its exact rational representation(so numbers that cannot be written exactly as floats wont be converted "correctly").

You can get more "human-readable" limiting the denominator:

>>> Fraction.from_float(3.333333333).limit_denominator(10)
Fraction(10, 3)

Even though it is trickier to understand which limit you should put to get the "correct" fraction, and it may happen that it is still impossible to obtain it due to the float representation.

If you have to stay with sympy than I don't think you can avoid using nsimplify, which seems written exactly for such purposes.

edit: from python2.7+ you can simply call Fraction(0.5) instead of using the from_float method.

like image 38
Bakuriu Avatar answered Oct 11 '22 08:10

Bakuriu