我最近在SympPy中遇到了一个无法修复的问题;我是图书馆的初学者,我花了很长时间在网上寻找解决方案,但没有找到,这就是我来这里的原因。
问题是:我有一个javascript web应用程序的输出,它给了我表达式(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中的一个错误,还是我做错了什么?
如果这个问题是众所周知的,并且我自己找不到任何关于它的信息,请原谅我。
正如在SymPy问题上指出的那样,这是有意的。这两个表达式对于一般复数CCD_ 6是不相等的。例如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
是非负的,则为真。如果b
是一个整数,那么(x**a)**b == x**(a*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)
如果你这样做,你需要小心,因为你应用的身份并不总是正确的,所以你可能会得到数学上不正确的结果。
这是sympy中的一个bug。
指数层次结构没有正确的展开(请参阅https://github.com/sympy/sympy/blob/master/sympy/core/power.py#L445)