Reputation: 35
I'm working in a C code for calculating pi with the precision of 80 decimals, using Archimedes method. This video may elucidate about the method.
I'm basically calculating Pi by starting with a regular hexagon with diameter 2, and sides measuring 1 and doing Pi = Perimeter/Diameter, and doubling the number of sizes so I can get a polygon closer to a circle each time my program calculates it.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
long double pi, circunferencia, s, s1, a, b, diametro;
int lado = 6;
s=1;
diametro = 2;
while (lado<=(6*pow(2,27))){
printf("numero de lados =%d\n", lado);
a= sqrt(1-(s/2)*(s/2));
// printf("a= %.80Lf\n", a);
b= 1 - a;
// printf("b= %.80Lf\n", b);
s1= sqrt ((b*b)+((s/2)*(s/2)));
// printf("c= %.80Lf\n", s1);
lado = lado*2;
s = s1;
circunferencia = lado * s1;
pi = circunferencia/diametro;
printf("\npi= %.80Lf\n\n\n", pi);
}
return 0;
}
With 227, I got up to about 15 decimals of precision, and lado = 805306368. If I do 228 or higher, the multiplication goes wrong from this part and I start to get negative numbers. Everything gets messed up and lado, suddenly is set to 0 and it turns into a infinite loop.
I'm a beginner in C and programming in general, if you guys could recommend me some reading on the subject, in order to understand how exactly this works and why am I getting this bug, it would be awesome.
I'm using Code::Blocks version 17.12, GNU GCC Compiler (I have "Have gcc follow the 2011 ISO C language standard [-std=c11]" option enabled, because I couldn't use "%Lf"
to refer to a long double
variable) and a Windows 10 x64 Operational System.
Upvotes: 2
Views: 1073
Reputation: 153468
If i do 2^28 or higher, the multiplication goes wrong from this part,
lado<=(6*pow(2,27))
is OK, yet lado = lado*2;
begins to overflow int
math about then.
Once lado > INT_MAX/2
(likely 1,073,741,823), int
overflow occurs with lado*2
and anything may happen. In OP's case, lado
eventually become 0.
Code could use long long
// int lado = 6;
long long lado = 6;
...
// printf("numero de lados =%d\n", lado);
printf("numero de lados =%lld\n", lado);
That will patch the immediate loop concern for about another 20 or so loops.
I have my doubts that code will achieve "calculating pi with the precision of 80 decimals" with long double
(maybe 17 - 34 decimal digits precision).
OP reported "my teacher said i could storage up to 80 digits with long double" certainty meant a long double
of 80 bits x86 extended precision format or about 20 decimal digits of precision.
I suggest using long double
functions instead of double
ones.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
long double pi, circunferencia, s, s1, a, b, diametro;
long long lado = 6;
s = 1;
diametro = 2;
while (lado <= (6 * pow(2, 27))) {
printf("numero de lados =%lld\t", lado);
// a = sqrt(1 - (s / 2) * (s / 2));
a = sqrtl(1 - (s / 2) * (s / 2));
b = 1 - a;
// s1 = sqrt((b * b) + ((s / 2) * (s / 2)));
s1 = hypotl(b, s / 2);
lado = lado * 2;
s = s1;
circunferencia = lado * s1;
pi = circunferencia / diametro;
printf("pi= %.40Lf\n", pi);
}
printf("best \tpi= %.40Lf\n", acosl(-1.0));
return 0;
}
Sample Output
numero de lados =6 pi= 3.1058285412302491482368360653509853364085
numero de lados =12 pi= 3.1326286132812381970275117382129792531487
numero de lados =24 pi= 3.1393502030468672071242958176995330177306
....
numero de lados =201326592 pi= 3.1415926535897932057699033503439522974077
numero de lados =402653184 pi= 3.1415926535897932296223511450250498455716
numero de lados =805306368 pi= 3.1415926535897932356938833109438746760134
best pi= 3.1415926535897932385128089594061862044327
// in my case good to about 1 23456789012345678 (18 digits)
Upvotes: 4