方法1:概率法求π的近似值。
概率法又称蒙特卡罗法。假设有一个半径为1的圆,则四分之一圆的面积等于1/4π。通过概率法计算出四分之一圆的面积,也就得到了1/4π。具体过程为:利用随机函数产生横坐标x和纵坐标y(两个值在0~1之间),接着判断由这两个随机数构成的点是否位于1/4圆的区域内,若该点位于1/4圆内则进行计数。由于随机函数生成的点坐标有一定的均匀性,当生成的点足够多时,就可得到阴影内和阴影外点的近似均匀分布。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int n, sum = 0;
double x, y;
printf("请输入点的数量:");
scanf("%d", &n);
srand((unsigned)time(NULL));
for (int i = 1; i < n; i++)
{
x = (double)rand() / RAND_MAX;
y = (double)rand() / RAND_MAX;
if (x * x + y * y <= 1)
{
sum += 1;
}
}
printf("PI = %f\n", (double)4 * sum / n);
return 0;
}
方法2:割圆法求π的近似值。
割圆法利用圆的内接多边形来逼近圆的周长。通过不断地将内接多边形进行切割划分,使其无限逼近圆周,则可得到精确度更高的π值。
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 1, PI;
int count, n = 0;
int s = 6; //初始内接圆边数
printf("请输入割圆次数:");
scanf("%d", &count);
while (n <= count)
{
printf("第%d次割圆,内接正%d边形:", n, s);
PI = s * x / 2;
printf("PI = %.12f\n", PI);
x = sqrt(2 - sqrt(4 - x * x));
s *= 2;
n += 1;
}
return 0;
}方法3:公式法求π的近似值。利用以下公式可方便计算π的近似值。π=2+2/3+2/3×2/5+2/3×2/5×3/7+2/3×2/5×3/7×4/9+?
#include <stdio.h>
int main(void)
{
double temp = 2, PI = 2;
int a = 1, b = 3; //a为分子,b为分母
while (temp > 1e-20)
{
temp *= (double)a / b;
PI += temp;
a += 1;
b += 2;
}
printf("PI = %.12f\n", PI);
return 0;
}注意:程序中需要根据精度要求结束循环。方法4:计算任意位数的π。
方法1至方法3计算出来的π值,由于使用单变量保存结果,限于计算机硬件对变量的表示范围有限,因此,最多只能计算出π值小数点后十多位。为了提高精度,可定义数组来逐位保存无限循环小数,基本思路仍然是利用方法3的公式法。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *temp, *pi;
int decLen; //小数位数
int a = 1, b = 3; //分子分母
int result, i, carry;
int count = 0, flag = 1; //计算次数
printf("请输入π的小数位数:");
scanf("%d", &decLen);
decLen += 2;
if (!(temp = (char *)malloc(sizeof(char) * decLen)))
{
return 0;
}
if (!(pi = (char *)malloc(sizeof(char) * decLen)))
{
return 0;
}
for (i = 0; i < decLen; i++)
{
*(pi + i) = 0;
*(temp + i) = 0;
}
pi[1] = 2; //初始化值
temp[1] = 2;
while (flag && ++count < 1e6)
{
carry = 0;
for (i = decLen - 1; i >= 0 ; i--)
{
result = temp[i] * a + carry;
temp[i] = result % 10;
carry = result / 10;
}
carry = 0;
for (i = 0; i < decLen; i++)
{
result = temp[i] + carry * 10;
temp[i] = result / b;
carry = result % b;
}
flag = 0;
for (i = decLen - 1; i > 0; i--)
{
result = pi[i] + temp[i];
pi[i] = result % 10;
pi[i - 1] += result / 10;
flag |= temp[i];
}
a += 1;
b += 2;
}
printf("计算了:%d次\n", count);
printf("PI = %d.", pi[1]); //输出个位和小数点
for (i = 2; i < decLen; i++)
{
if ((i > 2) && (i - 2) % 10 == 0)
{
printf(" ");
}
if ((i > 2) && (i - 2) % 50 == 0)
{
printf("\n");
}
printf("%d", pi[i]);
}
printf("\n");
return 0;
}
注意:终止循环的条件是:数组temp中全部为0,即已经没有余数需要处理。如果数组中元素一直不为0,则还需要设置另外的条件来终止循环,如规定循环处理次数。
原文地址:http://blog.csdn.net/mengwang024/article/details/39898131