Trying to find pi using when loops to a tolerance of 10^-4.

12 Ansichten (letzte 30 Tage)
I am attemping to use a "when" loop since I don't know how many iterations it'll take and need to to get it to the needed tolance. I'm stuck currently, but I think maybe adding another kinda of loop in the while loop would work. For example, if I use an "if" loop I can maybe get the code to stop when it reaches the pi vaule I want, but I'm also unsure how to stop it or how to use break.
Here's the code:
% summation of pi = 4 * (-1^(k+1))/(2*k-1) ;
k = 1 ; % starting index of the infinite series
iteration = 0 ; % starting iteration
while k < 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
k = (-1^(k+1))/(2*k-1) ; % infinite series of pi
iteration = 1 + iteration ;
% displays current iteration & vaule of pi
disp("Current Iteration: " + iteration)
disp("Current Vaule of pi: " + k)
end
a = k*4 ;
disp(a)

Akzeptierte Antwort

John D'Errico
John D'Errico am 8 Apr. 2024
Bearbeitet: John D'Errico am 8 Apr. 2024
Many, many things wrong in your code. I'm amazed nobody else as pointed most of them out. It was a start in the correct direction, but you need to be far more careful in how you write code. (Ok, at least one of the errors you made was something that would come as a surprise to even some much more seasoned users of MATLAB.)
This is the classic arc tangent series for pi/4, NOT pi. So you CANNOT compare the sum to pi. Yes, you multiplied by 4 at the end, but the comparison was done to pi. That is going to fail ALWAYS.
Next, comparing to the number 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
is meaningless, since MATLAB does not store hundreds of digits. Roughly 16 decimal digits. Anything past that is meaningless, a waste of CPU time to process it. Just use the existing value for pi, already stored in the constant pi. That is as accurate as anything you can store in a double already.
Next, the atan series is an ALTERNATING seriesm, where the terms are alternately positive and negative. So you need to be careful about the test you do in the while loop.
Next, you are using k as both an index, AND as the term in the series? Sorry, that will just produce complete crapola. Don't keep on overwriting k!!!!!!!!!
Next, you want to continue the while loop, as long as the error in the approximation is LARGER than tol. Note my use of absolute value in my code.
NEXT, there is a problem when raising a negative number to a power. For example, what is the square of -1? Naturally, you would write it as
-1^2
ans = -1
Do you see that is wrong? The problem is MATLAB needs you to write it as
(-1)^2
ans = 1
This is because the power operation has a higher precedence than the minus operation. So it raises 1 to that power, and THEN negates the result. This is not an issue if you store the number -1 into a variable first.
X = -1;
X^2
ans = 1
It got that one right of course.
Finally, your loop never sums up the elements in k to form a sum! As such, it will NEVER converge to anything useful.
Surprisingly, nobody pointed out most of these serious issues?
Anyway, I expect this series to take somewhere around 10000-20000 iterations before it gets into the correct ball park. There are of course hugely better approximation for pi. This ain't one of them. Total crap in fact, but we expect this series to take literally forever to do anything useful. It is only ever useful as a student assignment.
Anyway, I've dramatically cut the iteration displays there, only displaying a result every 1000 iterations. (I display more iterations for small k, just to see how the series is converging.)
% summation of pi = 4 * (-1^(k+1))/(2*k-1) ;
tol = 1e-4; % final tolerance on the approximation for pi
kmax = 1e5; % to insure we have not created an infinite loop if we made a mistake.
piapprox = 0 ; % eventual approximation to pi, starting the sum at 0
k = 1; % index
while (abs(4*piapprox - pi) > tol) && (k < kmax)
piapprox = piapprox + (-1)^(k+1)/(2*k-1) ; % infinite series for pi/4
k = k + 1;
% displays current iteration & value of pi
if ((k < 1000) && (mod(k,100) == 0)) || mod(k,1000) == 0
disp("Iteration: " + k + ", Current Approximation for pi: " + num2str(4*piapprox,6))
end
end
Iteration: 100, Current Approximation for pi: 3.15169 Iteration: 200, Current Approximation for pi: 3.14662 Iteration: 300, Current Approximation for pi: 3.14494 Iteration: 400, Current Approximation for pi: 3.1441 Iteration: 500, Current Approximation for pi: 3.1436 Iteration: 600, Current Approximation for pi: 3.14326 Iteration: 700, Current Approximation for pi: 3.14302 Iteration: 800, Current Approximation for pi: 3.14284 Iteration: 900, Current Approximation for pi: 3.14271 Iteration: 1000, Current Approximation for pi: 3.14259 Iteration: 2000, Current Approximation for pi: 3.14209 Iteration: 3000, Current Approximation for pi: 3.14193 Iteration: 4000, Current Approximation for pi: 3.14184 Iteration: 5000, Current Approximation for pi: 3.14179 Iteration: 6000, Current Approximation for pi: 3.14176 Iteration: 7000, Current Approximation for pi: 3.14174 Iteration: 8000, Current Approximation for pi: 3.14172 Iteration: 9000, Current Approximation for pi: 3.1417 Iteration: 10000, Current Approximation for pi: 3.14169
piapprox = piapprox*4;
disp("Final approximation: " + num2str(piapprox,16) + ", Error: " + (piapprox - pi))
Final approximation: 3.141492653590034, Error: -0.0001
OK. just for kicks, can we do better? With far fewer terms? Try this instead:
K = 1:100;
% this is just the seris you formed, for only the first 100 terms.
piapprox = 4*cumsum(((-1).^(K+1))./(2*K-1));
% The reshape and mean operations effectively average every pair of
% successive approximants. Since this is a slowly convergent alternatinvg
% series, that average will be hugely better.
betterpiapprox = mean(reshape(piapprox,2,[]));
betterpiapprox(end)
ans = 3.1416
betterpiapprox(end) - pi
ans = 5.0501e-05
So after only 100 terms in this far better approximation, we now have an error significantly less than that which was required, that took 10000 iterations to converge above.
  1 Kommentar
Sebastian
Sebastian am 8 Apr. 2024
Thank you for explaining it and showing examples that wer eeasy to follow .

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

KSSV
KSSV am 8 Apr. 2024
Try somewthing l;ike this:
% summation of pi = 4 * (-1^(k+1))/(2*k-1) ;
n_digits = 10 ;
iteration = 0 ; % starting iteration
val = vpa('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679',n_digits) ;
tol = vpa(10^-101,n_digits) ;
k = vpa(1,n_digits) ; % starting index of the infinite series
while (k-val)<=tol
k = (-1^(k+1))/(2*k-1) ; % infinite series of pi
iteration = 1 + iteration ;
% displays current iteration & vaule of pi
fprintf("Current Iteration: %d\n",iteration)
fprintf("Current Vaule of pi: %s\n", k)
end

Kategorien

Mehr zu Software Development Tools finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by