有啥方法可以在 sympy 中进行整数除法?

Posted

技术标签:

【中文标题】有啥方法可以在 sympy 中进行整数除法?【英文标题】:Any way to do integer division in sympy?有什么方法可以在 sympy 中进行整数除法? 【发布时间】:2017-05-05 04:42:09 【问题描述】:

我有一个很长的表达式,我认为可以简化,我认为sympy 将是完成它的完美方式。不幸的是,这个公式依赖于几个整数除法,我找不到任何方法来表示 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中有什么方法可以表示整数除法?

【问题讨论】:

你不能用floor吗? @SwiftsNamesake 也许我可以,但我没有想到。 help(floor) 产生的输出比我能快速消化的要多得多。 floor((x+1)/2) 结果为 floor(x/2 + 1/2)(我刚刚安装了 sympy 进行验证) @SwiftsNamesake:不幸的是,floor 不支持简化;看我的回答。 【参考方案1】:

标准

我假设您想要一个通过以下测试的函数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 支持模运算并能够对其进行简化,因此该函数通过了上述测试。但是,如果无法进行完全简化,您最终会得到可能不需要的模表达式。

楼层

正如 cmets 中已经提到的,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))(您需要在测试中使用positive=True 来表示x) .【参考方案2】:

创建分段函数可能是要走的路。它将响应简化请求,并根据参数相对于您要除以的整数的模数来保存可能的各种解决方案。在有多个整数除法的表达式上使用 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))

【讨论】:

以上是关于有啥方法可以在 sympy 中进行整数除法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在javascript中进行整数除法(在int中获取除法答案而不是float)? [复制]

用非常数除数进行矢量化整数除法的最快方法

在 Python 中,整数除法中向零舍入的好方法是啥?

C整数除法和下限

使用 ilnumerics 进行整数除法

如何解决使用 Z3 产生整数结果的整数除法?