使用 Jm+1=2mj(m) -j(m-1) 公式在 MATLAB 中计算贝塞尔函数
我尝试使用该公式实现贝塞尔函数,这是代码:
function result=Bessel(num);
if num==0
result=bessel(0,1);
elseif num==1
result=bessel(1,1);
else
result=2*(num-1)*Bessel(num-1)-Bessel(num-2);
end;
但是如果我使用 MATLAB 的贝塞尔函数将其与此函数进行比较,我会得到太高的不同值。 例如,如果我输入 Bessel(20) 它会给我 3.1689e+005 作为结果,如果我输入 bessel(20,1) 它会给我 3.8735e-025 ,这是一个完全不同的结果。
I tried to implement bessel function using that formula, this is the code:
function result=Bessel(num);
if num==0
result=bessel(0,1);
elseif num==1
result=bessel(1,1);
else
result=2*(num-1)*Bessel(num-1)-Bessel(num-2);
end;
But if I use MATLAB's bessel function to compare it with this one, I get too high different values.
For example if I type Bessel(20) it gives me 3.1689e+005 as result, if instead I type bessel(20,1) it gives me 3.8735e-025 , a totally different result.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这种递归关系在数学上很好,但在使用浮点数的有限精度表示实现算法时在数值上不稳定。
考虑以下比较:
因此,您可以看到计算值在 9 之后如何开始显着不同。
根据 MATLAB:
并给出以下实施参考:
such recurrence relations are nice in mathematics but numerically unstable when implementing algorithms using limited precision representations of floating-point numbers.
Consider the following comparison:
So you can see how the computed values start to differ significantly after 9.
According to MATLAB:
and gives the following as references for their implementation:
您使用的前向递归关系不稳定。要了解原因,请考虑 BesselJ(n,x) 的值变得越来越小,大约减小了
1/2n
倍。您可以通过查看 J 的泰勒级数的第一项来看到这一点。因此,您所做的就是从一个稍小的数字的倍数中减去一个大的数字,以获得一个更小的数字。从数字上看,这不会很好地发挥作用。
这么看吧。我们知道结果的数量级为
10^-25
。您从 1 数量级的数字开始。因此,为了从中获得哪怕一位准确的数字,我们必须知道前两个数字,精度至少为 25 位。我们显然不这么认为,而且重复率实际上是有分歧的。使用相同的递推关系,从高阶到低阶,是稳定的。当您从 J(20,1) 和 J(19,1) 的正确值开始时,您也可以完全准确地计算低至 0 的所有阶数。为什么这有效?因为现在每一步的数字都在变大。您从一个较大数字的精确倍数中减去一个非常小的数字,以获得一个更大的数字。
The forward recurrence relation you are using is not stable. To see why, consider that the values of BesselJ(n,x) become smaller and smaller by about a factor
1/2n
. You can see this by looking at the first term of the Taylor series for J.So, what you're doing is subtracting a large number from a multiple of a somewhat smaller number to get an even smaller number. Numerically, that's not going to work well.
Look at it this way. We know the result is of the order of
10^-25
. You start out with numbers that are of the order of 1. So in order to get even one accurate digit out of this, we have to know the first two numbers with at least 25 digits precision. We clearly don't, and the recurrence actually diverges.Using the same recurrence relation to go backwards, from high orders to low orders, is stable. When you start with correct values for J(20,1) and J(19,1), you can calculate all orders down to 0 with full accuracy as well. Why does this work? Because now the numbers are getting larger in each step. You're subtracting a very small number from an exact multiple of a larger number to get an even larger number.
您只需修改下面用于球面贝塞尔函数的代码即可。它经过充分测试,适用于所有参数和顺序范围。抱歉,这是 C# 语言
You can just modify the code below which is for the Spherical bessel function. It is well tested and works for all arguments and order range. I am sorry it is in C#