有没有办法在sympy中进行整数除法?

7

我有一个非常长的表达式,我认为可以简化,我想用sympy来完成它。不幸的是,公式依赖于一些整数除法,我找不到任何表示这些除法的方法。

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

显然不是我想要的,1/2 不是一个整数。

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

显然,sympy 无法处理 //
>>> Integer((x+1)/2)
#   A long list of error messages, ending with ...
TypeError: Integer can only work with integer expressions.

看起来Integer只适用于常数,而不是公式。

有一个函数trunc,但它似乎没有类似于我想要的功能。

sympy中有表示整数除法的方法吗?


1
你不能使用 floor 吗? - SwiftsNamesake
@SwiftsNamesake 或许我可以,只是没想到。help(floor) 产生的输出太多了,我无法快速消化。 - Mark Ransom
floor((x+1)/2)的结果为floor(x/2 + 1/2)(我刚刚安装了Sympy进行验证) - SwiftsNamesake
@SwiftsNamesake:很遗憾,floor不支持简化;请看我的答案。 - Wrzlprmft
2个回答

8

标准

我假设您需要一个函数div,该函数通过以下测试:

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

模运算

使用模运算符,您可以实现整数除法,如下所示:

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

由于SymPy支持模运算并能够简化它,因此该函数通过了上述测试。但是,如果无法进行完全简化,则会得到可能不需要的模表达式。

地板除

正如在评论中已经提到的那样,SymPy提供了一个floor函数,可以用来获取整数除法(这也是表达式中//运算符的实现方式):

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

然而,floor 不支持简化,因此未通过第二个测试。

我将这个与 Piecewise() 结合使用来处理截断除法(向零舍入而不是向负无穷大舍入):Piecewise(((a + -a % b) / b, (a < 0) & (b > 0)), ((a - a % -b) / b, (b < 0) & (a > 0)), ((a - a % b) / b, True))(在测试中,您需要对 x 使用 positive=True)。 - Martijn Pieters

0
创建一个分段函数可能是解决问题的方法。它将响应简化请求,并将保留可能的解决方案变体,这取决于参数相对于您正在除以的整数的模数。在存在多个整数除法的表达式上使用piecewise_flatten可能需要将所有内容折叠在一起。
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)

例如,
>>> 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))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接