为什么 SymPy 的积分有时会产生非常长的反导数?
Why does SymPy's integrate sometimes produce antiderivative with very long numbers?
这是在 SymPy 1.1.1 上使用 Python 3.6.5.
在 SymPy 中,我总是不得不在被积函数周围使用 S('...')
以使其不是 return 使用浮点数的结果,有时是为了使其实际计算积分。这样做的一个副作用是 SymPy 有时 return 的结果非常长,例如
z=symbols('z')
integrate(S('1/(cos(z)+sin(z)+2**(1/2))'),z)
returns
-221108036964586978124740847487718783991180811173992192658
5647118334188786/(-2669010107947987550795474273552499757111
367990811651140108173443831125763*tan(z/2) +
18872751463854612207095892554955468385336360233408060517004
98501499110078*sqrt(2)*tan(z/2) - 7817349615625263300858850180
569529185777319674708450884076749
42332015685*sqrt(2) + 110554018482293489062370423743859391995
5904055869960963292823559167094393) +
1563469923125052660171770036113905837155463934941690176815349
884664031370*sqrt(2)/(-2669010107947987550795474273552499757
111367990811651140108173443831125763*tan(z/2) +
18872751463854612207095892554955468385336360233408060517004985
01499110078*sqrt(2)*tan(z/2) - 78173496156252633008588501805695
29185777319674708450884076749
42332015685*sqrt(2) + 11055401848229348906237042374385939199559
04055869960963292823559167094393)
我验证了上面的结果是正确的。在上面做 simplify()
没有帮助。我一开始以为是结果需要简化,仅此而已。
如果我不使用 S'(....)'
和 sympy,它不会评估
这个例子。
>>> integrate(1/(cos(z)+sin(z)+2**(1/2)),z)
1.0*Integral(1/(1.0*sin(z) + 1.0*cos(z) + 1.4142135623731), z)
但与 fricas 1.3.3 的小输出相比
integrate(1/(cos(z)+sin(z)+2^(1/2)),z)
((-1)*2^(1/2)*sin(z)+((-1)*2^(1/2)*cos(z)+2))/(2*sin(z)+(-2)*cos(z))
数学 11.3
ClearAll[z]
FullSimplify[Integrate[1/(Cos[z] + Sin[z] + 2^(1/2)), z]]
-(((1 + I) + (2*I + Sqrt[2])*E^(I*z))/((1 + I) + Sqrt[2]*E^(I*z)))
枫叶2018
int(1/(cos(z)+sin(z)+2^(1/2)),z);
-2/((2^(1/2)-1)*(tan((1/2)*z)+2^(1/2)+1))
问题:SymPy的积分算法中有什么有时
使其输出如此长的数字,而其他 CAS 系统
不求同一个积分? SymPy 中有什么技巧可以使
与其他 CAS 系统相比,它产生的叶尺寸结果更小?
同样,SymPy 的结果是正确的。我只是问为什么这个例子的结果有这么长的数字。可能如果有人知道为什么,这将有助于更好地理解事情。
我可以猜到答案来自 "heuristic Risch algorithm",它在某些步骤匹配许多(拆开的)表达式的系数,并以完成这项工作的大系数结束。实际上,简化表达式 before 集成恰好有帮助:
>>> integrate(trigsimp(1/(cos(z)+sin(z)+sqrt(2))), z)
-sqrt(2)/(tan(z/2 + pi/8) + 1)
(可以在这里使用 simplify
来达到同样的效果,但是如果您知道这里需要三角化简,那么 trigsimp
就是正确的方法。)一旦表达式被简化为
sqrt(2)/(2*(sin(z + pi/4) + 1))
只剩下一个三角函数,这比处理两个容易多了。
(另外:使用 sqrt(2)
代替 2**(1/2)
是避免将 1/2
过早评估为浮点数的更好方法,而不是将整个公式字符串化。)
这是在 SymPy 1.1.1 上使用 Python 3.6.5.
在 SymPy 中,我总是不得不在被积函数周围使用 S('...')
以使其不是 return 使用浮点数的结果,有时是为了使其实际计算积分。这样做的一个副作用是 SymPy 有时 return 的结果非常长,例如
z=symbols('z')
integrate(S('1/(cos(z)+sin(z)+2**(1/2))'),z)
returns
-221108036964586978124740847487718783991180811173992192658
5647118334188786/(-2669010107947987550795474273552499757111
367990811651140108173443831125763*tan(z/2) +
18872751463854612207095892554955468385336360233408060517004
98501499110078*sqrt(2)*tan(z/2) - 7817349615625263300858850180
569529185777319674708450884076749
42332015685*sqrt(2) + 110554018482293489062370423743859391995
5904055869960963292823559167094393) +
1563469923125052660171770036113905837155463934941690176815349
884664031370*sqrt(2)/(-2669010107947987550795474273552499757
111367990811651140108173443831125763*tan(z/2) +
18872751463854612207095892554955468385336360233408060517004985
01499110078*sqrt(2)*tan(z/2) - 78173496156252633008588501805695
29185777319674708450884076749
42332015685*sqrt(2) + 11055401848229348906237042374385939199559
04055869960963292823559167094393)
我验证了上面的结果是正确的。在上面做 simplify()
没有帮助。我一开始以为是结果需要简化,仅此而已。
如果我不使用 S'(....)'
和 sympy,它不会评估
这个例子。
>>> integrate(1/(cos(z)+sin(z)+2**(1/2)),z)
1.0*Integral(1/(1.0*sin(z) + 1.0*cos(z) + 1.4142135623731), z)
但与 fricas 1.3.3 的小输出相比
integrate(1/(cos(z)+sin(z)+2^(1/2)),z)
((-1)*2^(1/2)*sin(z)+((-1)*2^(1/2)*cos(z)+2))/(2*sin(z)+(-2)*cos(z))
数学 11.3
ClearAll[z]
FullSimplify[Integrate[1/(Cos[z] + Sin[z] + 2^(1/2)), z]]
-(((1 + I) + (2*I + Sqrt[2])*E^(I*z))/((1 + I) + Sqrt[2]*E^(I*z)))
枫叶2018
int(1/(cos(z)+sin(z)+2^(1/2)),z);
-2/((2^(1/2)-1)*(tan((1/2)*z)+2^(1/2)+1))
问题:SymPy的积分算法中有什么有时 使其输出如此长的数字,而其他 CAS 系统 不求同一个积分? SymPy 中有什么技巧可以使 与其他 CAS 系统相比,它产生的叶尺寸结果更小?
同样,SymPy 的结果是正确的。我只是问为什么这个例子的结果有这么长的数字。可能如果有人知道为什么,这将有助于更好地理解事情。
我可以猜到答案来自 "heuristic Risch algorithm",它在某些步骤匹配许多(拆开的)表达式的系数,并以完成这项工作的大系数结束。实际上,简化表达式 before 集成恰好有帮助:
>>> integrate(trigsimp(1/(cos(z)+sin(z)+sqrt(2))), z)
-sqrt(2)/(tan(z/2 + pi/8) + 1)
(可以在这里使用 simplify
来达到同样的效果,但是如果您知道这里需要三角化简,那么 trigsimp
就是正确的方法。)一旦表达式被简化为
sqrt(2)/(2*(sin(z + pi/4) + 1))
只剩下一个三角函数,这比处理两个容易多了。
(另外:使用 sqrt(2)
代替 2**(1/2)
是避免将 1/2
过早评估为浮点数的更好方法,而不是将整个公式字符串化。)