我最近遇到了一个我无法修复的 SympPy 问题;我是图书馆的新手,我花了很多时间在网上寻找解决方案,但没有找到,这就是我来到这里的原因。
这就是问题所在:我有一个 javascript 网络应用程序的输出,它给我表达式 (x**2)**(1/3) 而不是 x**( 2/3)。 “没问题”,我想,“SymPy 会解析它”……但不是。如果我比较,我会得到这样的结果:
>>> sympify("(x**2)**(1/3)") == sympify("x**(2/3)")
False
我进行了一些测试,但我只得到了符号表达式中的指数。示例:
>>> (x**(1/3))**2 == x**(2/3)
True
更奇怪的是,如果我反转两个指数,我会得到正确的结果:
>>> sympify("(x**(1/3))**2") == sympify("x**(2/3)")
True
我尝试使用simplify 和extend,但它们都不起作用。我能得到好的结果的唯一方法是使用 eval,但这需要先创建一个符号“x”,这是我做不到的,因为我无法确切知道哪些符号是将在表达式中使用。
所以问题来了:这是 SymPy 中的错误,还是我做错了什么?
如果这个问题是众所周知的,而我自己找不到任何相关信息,请原谅。
请您参考如下方法:
正如在 the SymPy issue 上指出的那样,这是故意的。这两个表达式对于一般复数 x 是不相等的。以 x = -1 为例,((-1)**2)**(1/3) == 1**(1/3) == 1,而 (-1)**(2/3) = -1/2 + sqrt(3)/2*I。参见 http://docs.sympy.org/0.7.3/tutorial/simplification.html#powers了解更多信息。如果 SymPy 知道它对整个域都是正确的,它只会简化这些指数。
特别是,如果 x 为非负数,则此为为真。 (x**a)**b == x**(a*b) 如果 b 是整数,这也是您的其他测试有效的原因。
如果你想强制简化这个,有两个主要选项。一种(最佳选择)是假设 x 是非负数或正数。
>>> x = symbols('x', positive=True)
>>> (x**2)**(S(1)/3)
x**(2/3)
如果你想在从字符串解析后用正版本替换你的符号,你可以使用 posify:
>>> posify((x**2)**(S(1)/3))
(_x**(2/3), {_x: x})
或者您可以使用 sympify 的 locals 参数手动设置 {'x': Symbol('x', positive=True}.
另一种方法,如果这不能完全满足您的需求,则使用 powdenest 强制简化它:
>>> x = symbols('x') # No assumptions on x
>>> (x**2)**(S(1)/3)
(x**2)**(1/3)
>>> powdenest((x**2)**(S(1)/3), force=True)
x**(2/3)
如果您这样做,您需要小心,因为您应用的恒等式并不总是正确的,因此您最终可能会得到数学上不正确的结果。
