如何在Sympy中获得cos(x)* cosh(x)== 1的所有解?

时间:2014-12-09 07:33:59

标签: sympy

以下是我能得到的最好的。

map(lambda n: nsolve(cos(x)*cosh(x)-1,x,3.14/2+3.14*n),range(9))

[mpf('0.0039941152964418809'),
 mpf('4.730040744862704'),
 mpf('7.8532046240958376'),
 mpf('10.995607838001671'),
 mpf('14.137165491257464'),
 mpf('17.278759657399481'),
 mpf('20.420352245626061'),
 mpf('23.561944902040455'),
 mpf('26.703537555508186')]

如果将范围(9)更改为范围(10),则sympy将返回错误。

ValueError: Could not find root within given tolerance. (1.59798e-17 > 2.1684e-1
9)
Try another starting point or tweak arguments.

我在Mathematica网站上问过这个问题,Mathematica似乎可以提供非常准确和快速的解决方案。看看这个:how-to-obtain-all-solutions-for-cosx-coshx-1

1 个答案:

答案 0 :(得分:1)

这是使用智能初始猜测的一个很好的例子。如果您只是提供公差,您可以找到其他解决方案:

>>> len([nsolve(cos(x)*cosh(x)-1,x,3.14/2+3.14*n,tol=1e-12) for n in range(10)])
10

但是,请注意,函数在根区域中非常陡峭,并且不太可能每个结果都会有x值使函数值变小。如果您知道您的初始猜测导致根而不是不连续,您可以安全地使用verify = False跳过解决方案的验证(并自行验证,也许考虑斜率)。我总是觉得使用bisect方法更安全,但在这些情况下:

>>> f
cos(x)*cosh(x) - 1
>>> bounds = lambda i: (3.14*i, 3.14*(i+1))
>>> root = lambda i: nsolve(f, bounds(i), solver='bisect', verify=False)

>>> root(0)
mpf('0.0')
>>> root(99)
mpf('312.58846903218443')
>>> root(100)
mpf('315.73006168577422')

你可以看到此时的函数非常大,但如果我们通过函数的导数进行归一化,答案看起来会更好:

>>> ans = _
>>> f.subs(x, ans).n(2)
2.3e+122
>>> (f/f.diff(x)).subs(x, ans).n(2)
-3.4e-15

注意:目前,将规范化函数传递给nsolve是行不通的,因此它可以在求解过程中使用:nsolve只适用于你传递的函数的分子。