我正在使用C语言使用Archimedes方法以80位小数的精度计算pi。 This video可能会阐明该方法。
我基本上是从直径为2的正六边形开始,边的尺寸为1,然后做 Pi =周长/直径,然后将尺寸数加倍,从而得出多边形每当我的程序计算出它时,它就会接近一个圆。
代码如下:
#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;
}
使用2 27 ,我的精度达到15位小数,并且 lado =805306368。如果我执行2 28 或更高,这部分的乘积是错误的,我开始得到负数。一切都搞砸了, lado 突然变成了0,变成了无限循环。
我一般是C和程序设计的初学者,如果你们可以推荐给我一些有关该主题的文章,以了解它的工作原理以及我为什么得到此错误,那就太棒了。
我使用的是Code :: Blocks版本17.12,GNU GCC编译器(我启用了 gcc遵循2011 ISO C语言标准[-std = c11] ”选项,因为我无法不要使用"%Lf"
来引用long double
变量)和Windows 10 x64操作系统。
答案 0 :(得分:4)
如果我的分数是2 ^ 28或更高,则乘法在这一部分会出错,
lado<=(6*pow(2,27))
还可以,但是lado = lado*2;
大约在此时开始溢出int
数学。
一旦lado > INT_MAX/2
(可能是1,073,741,823),int
就会发生lado*2
溢出,并且可能发生任何事情。对于OP,lado
最终变为0。
代码可以使用long long
// int lado = 6;
long long lado = 6;
...
// printf("numero de lados =%d\n", lado);
printf("numero de lados =%lld\n", lado);
这将使立即循环问题再修补约20或 这样循环。
我怀疑代码是否可以使用long double
(可能是17-34个十进制数字的精度)来实现“以80个十进制的精度计算pi”。
OP报告“我的老师说我最多可以存储80位数字,并具有长双精度”,这意味着{long double
为80位位 x86 extended precision format或十进制为20位位数。
我建议使用long double
个函数,而不要使用double
个函数。
#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;
}
样本输出
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)