Bessel Function Calculation in Matlab
34 次查看(过去 30 天)
显示 更早的评论
I was trying to get the result for Bessel function of first kind by using the bessel function main equation and Matlab builtin bessel function.But I am getting good result for builtin function but while using the actual equationa at certain point my series starts divergeing instead of converging.I am giving the codes I haved used
n=1
JnE=0;
for z=11:60
for k=0:100
JnE = JnE+(((-1)^k))/(factorial(k)*factorial(k+n+1))*(z/2)^(2*k+n);
end
fprintf('JnEz=%f\n',JnE)
end
Can anyone tell me where I am doing it wrong?
I am also giving my code by using besselj function
format short
n=1
for z=11:60
JnE=besselj(n,z)
end
0 个评论
采纳的回答
Walter Roberson
2023-2-22
Are you sure that you want to be totaling from z = 11 to z = 60? You only set JnE to zero before the z loop.
You are running into problems with factorial(k) losing precision.
But your big problem was that you had factorial(k+n+1) when you needed gamma(k+n+1) -- when you rewrote as factorial you forgot to subtract the 1.
syms k
n=1
JnE=0;
for z=11:60
part = symsum((((-1)^k))/(factorial(k)*gamma(k+n+1))*(z/2)^(2*k+n), k, 0, 100);
JnE = JnE + double(part);
bess = besselj(n,z);
fprintf('(%d) part = %f, cumulative = %f, besselj = %f\n', z, part, JnE, bess);
end
3 个评论
Walter Roberson
2023-2-22
Good question, and I do not know. When I examine the terms, they all appear to be reasonable to me, and since each is a symbolic rational, they sum to a symbolic rational, and I cannot see any reason why that rational would not be the 9.4-ish that is being reported. So I do not know what is going wrong.
更多回答(3 个)
David Hill
2023-2-22
You need to increase your k as z gets larger.
n=sym(1);
F(1)=n;
for k=1:202
F(k+1)=F(k)*k;
end
J=zeros(1,60);
for z=1:100
JnE=sym(0);
for k=0:200%this is suppose to be 0 to infinity!
JnE = JnE+(((-1)^k))/(F(k+1)*F(k+2))*(sym(num2str(z))/2)^(2*k+1);
end
J(z)=double(JnE);
JJ(z)=besselj(1,z);
J(z)-JJ(z)
end
John D'Errico
2023-2-22
编辑:John D'Errico
2023-2-23
Several common problems in this, regardless of whether you got the factiorial/gamma problem solved.
You want to use a series solution for a problem with large values of the argument. When the terms are alternating in sign, how well does that work? LOOK AT THE TERMS!
First, do you have the correct terms in the series?
Next, NEVER use factorial on problems like this. In fact, a good idea is to NEVER use gamma either. Instead, form the terms by taking the log of each term. That will use the gammaln function. At least this way you can avoid overflows and underflows. Remember that a double precision number has a limited dynamic range.
Your task was to compute the series for besselj(1,z), where z is moderately large.
k = (0:100)';
z = 10:10:60; % I'll just write the problem using a few values for z.
n = 1;
% compute the natural logs of all terms, from 0:100
besseltermsln = -gammaln(k+1) - gammaln(k + n + 1) + (2*k+n)*log(z/2);
Now, remember, these terms will be exponentiated, and they alternate in sign.
plot(k,besseltermsln,'-')
legend('10','20','30','40','50','60')
grid on
Looking at that plot, you probably had a chance to compute the bessel function for z=10. But z=60? Even z=30 is probably questionable, but you might just make it.
Maybe what I need to do is to exponentiate the terms next.
semilogy(k,exp(besseltermsln),'-')
legend('10','20','30','40','50','60')
grid on
The problem will be massive subtractive cancellation. Adding and subtracting numbers, each of which is on the order of 1e16 or larger, means you loose all information content in the result. Now lets compute the sum of that series.
S = (-1).^k;
seriessum = cumsum(S.*exp(besseltermsln),1);
Now, for example, look at the series for z==10. The value should be
format long g
besselj(n,10)
plot(seriessum(:,1))
so those alternating sums have terms as large as oughly 350. But the final series result should be tiny. That tells me you will never get a sum that is accurate to better than roughly 1e-12 or so.
seriessum(end,1)
seriessum(end,1) - besselj(n,10)
Now, do the same computations for z=20. First, again I'll plot the series, to see how well it is converging.
plot(seriessum(:,2))
seriessum(end,2)
besselj(n,20)
seriessum(end,2) - besselj(n,20)
Here, we see that we will be losing roughly 7 of the lower order digits in the result.
And as I predicted, by the time you get to z=30, you will have only the top couple of the highest order digits correct.
[besselj(n,30),seriessum(end,3),seriessum(end,3) - besselj(n,30)]
And finally, you should see that besselj(1,40) cannot be computed in double precision using that series as you want to do. The result is complete garbage at that point, and certainly beyond. Of course, this is probably the reason you were asked to do this homework assignment. You would need to use higher precision arithmetic to gain any hope of convergence.
[besselj(n,40),seriessum(end,4),seriessum(end,4) - besselj(n,40)]
the cyclist
2023-2-22
There are a handful of mistakes in your code:
- In one place, you used factorial instead of the gamma function. (You need to subtract 1 from the input argument, to use factorial).
- You should have set the starting value JnE to zero for each value of z (i.e. instead the loop over z).
- You have ignored the numerical precision that MATLAB can handle here. When the factorials and other factors get big, they are no longer stored precisely enough to be numerically stable.
In the code below, I have fixed the first two problems, and maxxed out your value of z to 30. You can see the two values are close, but also you are just starting to see the round-off error sneaking in.
n=1;
for z=11:30
JnE = 0;
for k=0:100
JnE = JnE+(((-1)^k))/(factorial(k)*factorial(k+n))*(z/2)^(2*k+n);
end
end
fprintf('JnEz=%f\n',JnE)
n=1;
for z=11:30
JnE=besselj(n,z);
end
fprintf('JnEz=%f\n',JnE)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Bessel functions 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!