简体   繁体   English

在SymPy中集成1 / x

[英]Integration of 1/x in SymPy

I think it's good that SymPy returns log(x) when integrating 1/x, instead of log(abs(x)). 我认为Sympy在集成1 / x时返回log(x)而不是log(abs(x))很好。 This keeps it simple and lets the user worry about the signs. 这使其简单,并使用户担心这些标志。

However, there are situations where it leads to the wrong answer. 但是,在某些情况下会导致错误的答案。 For example, 例如,

from sympy import *
x = Symbol('x')
integrate(cos(x)**2/sin(x), x)

results in 结果是

log(cos(x) - 1)/2 - log(cos(x) + 1)/2 + cos(x)

while it should (clearly?) be 虽然应该(显然?)是

log(1 - cos(x))/2 - log(1 + cos(x))/2 + cos(x)

Is there a workaround that will yield the second answer? 有没有变通办法会产生第二个答案?

The absence of abs is not just to "keep it simple". 缺少abs不仅仅是为了“保持简单”。 As the SymPy lead developer wrote , 正如SymPy首席开发人员所写的那样

SymPy doesn't return log(abs(x)) for integrate(1/x) because it isn't valid for complex numbers. SymPy不会为integrate(1/x)返回log(abs(x)) ,因为它对复数无效。 Instead, the answer is correct up to an integration constant (which may be complex). 相反,答案是正确的,直到积分常数(可能很复杂)。 All SymPy operations assume that variables are complex by default. 默认情况下,所有SymPy操作都假定变量是复杂的。

The rest of the linked issue is also relevant to your question. 链接的问题的其余部分也与您的问题有关。 From a certain point of view, log(cos(x) - 1) : is as valid as log(1 - cos(x)) in the result of integration: the difference between these two expressions is I*pi , which is absorbed by the constant of integration. 从特定角度来看, log(cos(x) - 1) :在积分结果中与log(1 - cos(x))一样有效:这两个表达式之间的差为I*pi ,被吸收通过不断的整合。 Besides, cos(x) could be greater than 1 for complex x, like cos(I) = 1.54... 此外,对于复数x, cos(x)可能大于1,例如cos(I) = 1.54...

That said, the following is a way to force the constant term in logs to be nonnegative. 也就是说,以下是一种将对数中的常数项强制为非负数的方法。

def fix_logs(expr):
    replacements = {}
    for a in expr.atoms(log):
        if a.args[0].as_coeff_add()[0].is_negative:
            replacements[a] = log(-a.args[0]) + log(-1)
    return expr.xreplace(replacements)

Here is how it works: 下面是它的工作原理:

rv = integrate(cos(x)**2/sin(x), x)
rv2 = fix_logs(rv)
rv3 = Add(*fix_logs(rv2).as_coeff_add(x)[1])

Here rv, rv2, and rv3 are: 这里rv,rv2和rv3是:

log(cos(x) - 1)/2 - log(cos(x) + 1)/2 + cos(x)
log(-cos(x) + 1)/2 - log(cos(x) + 1)/2 + cos(x) + I*pi/2
log(-cos(x) + 1)/2 - log(cos(x) + 1)/2 + cos(x)

The function fix_logs does not remove the log(-1) part because it could be important: x*log(x-1) becomes x*(log(1-x) + I*pi/2) where the constant cannot be simply dropped. fix_logs函数不会删除log(-1)部分,因为它可能很重要: x*log(x-1)变为x*(log(1-x) + I*pi/2) ,其中常量不能简单地表示掉了。 But if desired, the additive constant can be removed as shown in the calculation of rv3 . 但是,如果需要,可以像rv3的计算所示那样除去加性常数。

Reference for as_coeff_add method as_coeff_add方法的参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM