Any way to do a whole division in sympy?

I have a very long expression that I think can be simplified, and I thought sympy would be the perfect way to do this. Unfortunately, this formula relies on a couple of integer divisions, and I cannot find a way to represent them in sympy .

 >>> x=Symbol('x') >>> (x+1)/2 x/2 + 1/2 

Obviously I do not want 1/2 not an integer.

 >>> (x+1)//2 TypeError: unsupported operand type(s) for //: 'Add' and 'int' 

Obviously sympy does not handle // .

 >>> Integer((x+1)/2) # A long list of error messages, ending with ... TypeError: Integer can only work with integer expressions. 

Integer seems to be designed to work with constant numbers only, not formulas.

There is a trunc function, but it doesn't seem to do anything like what I want.

Is there a way to represent integer division in sympy ?

+8
python integer-division sympy
source share
2 answers

Criteria

I assume that you want the div function to pass the following tests:

 from sympy import sympify, simplify, Symbol def test_div(div): # check that div behaves as intended for integers for i in range(-5,5): for j in range(-5,5): if j==0: continue assert i//j == div(sympify(i),sympify(j)) # check that div's output can be simplified x = Symbol("x", integer=True) assert simplify( div(x+1,2) - div(x-1,2) ) == 1 

Modular

You can implement integer division using the modulo operator as follows:

 div = lambda x,y: (xx%y)/y 

Since SymPy supports modular arithmetic and can simplify it, this function passes the above tests. However, if complete simplification is not possible, you will get modulo-expressed expressions that may be undesirable.

Floor

As mentioned in the comments, SymPy provides a floor function that can be used to obtain integer division (just like the // operator for expressions):

 div = lambda x,y: sympy.floor(x/y) 

However, floor does not support simplifications and therefore does not perform the second test.

+5
source share

Creating a piecewise function can be a way. It will respond to a simplification request and will contain solutions depending on the module of the argument regarding the integer by which you divide. Using piecewise_flatten in an expression that has multiple integer divisions is likely to be necessary to collapse everything together.

 def idiv(n, d): from sympy.core.compatibility import as_int d = as_int(d); assert d > 0 args = [] for i in range(d): N = n - i args.append((N/d, Eq(Mod(N, d), i))) args[-1] = (args[-1][0], True) return Piecewise(*args) 

For example,

 >>> print(factor_terms(idiv(x+1,3))) Piecewise( ((x + 1)/3, Eq(Mod(x + 1, 3), 0)), (x/3, Eq(Mod(x, 3), 1)), ((x - 1)/3, True)) 
+1
source share

All Articles