读书人

用内接法和外切法求π结果精度相差比

发布时间: 2012-03-23 12:06:21 作者: rapoo

用内接法和外切法求π,结果精度相差比较大
起始都是正六边形,然后边数翻倍。发现内接法比外切法计算结果更精确。

准确值:π=3.14159265358979323846264338……
内接法:π=3.141592653589794
外切法:π=3.141592671741286

两种方法的代码在下面。
不知道是不是我外切法的算法里面,位数取得不对。
麻烦各位帮忙看看。谢谢。

#include <stdio.h>
#include <math.h>

void main()
{
double e,b=1,d;//b:为正多边形边长
long int i;//i:正多边形边数
for(i=6;;i*=2)//正多边形边数加倍
{
e=b;//e:暂存边数为加倍前的边长
d=1.0-sqrt(1.0-b*b/4);//计算圆内接正多边形的边长
b=sqrt(b*b/4+d*d);
if(2*i*b-i*e <1e-15)
{
break;//精度达1e-15则停止计算
}
e=b;//保存本次正多边形的边长作为下一次精度控制的依据
}
printf( "π=%.15lf\n ",i*b);//输出π值和正多边形的边数
printf( "The number of edges of required polygon:%ld\n ",i);
}

//运行结果
//π=3.141592653589794
//The number of edges of required polygon:100663296

//外切法:

#include <stdio.h>
#include <math.h>

void main()
{
double e,b=2*sqrt(3)/3,d;//b:为正多边形边长
long int i;//i:正多边形边数
for(i=6;;i*=2)//正多边形边数加倍
{
e=b;//e:暂存边数为加倍前的边长
d=sqrt(1.0+b*b/4)-1;//计算圆外切正多边形的边长
b=2*(sqrt(b*b+4)-2)/b;
if(i*e-2*i*b <1e-15)
{
break;//精度达1e-15则停止计算
}
e=b;//保存本次正多边形的边长作为下一次精度控制的依据
}
printf( "π=%.15lf\n ",i*b);//输出π值和正多边形的边数
printf( "The number of edges of required polygon:%ld\n ",i);
}

//运行结果
//π=3.141592671741286
//The number of edges of required polygon:49152

[解决办法]
我看了下,阁下的公式的确没错

我的公式:b=2*(b*b/4-d*d)/b;//1
而d=sqrt(b*b/4+1)-1;//2
2代入1的确能得到b=2*(sqrt(b*b+4)-2)/b;


公式是对的,那就只存在精度的问题了
找出误差所在:lz可以试下,用我的公式:b=2*(b*b/4-d*d)/b(误差较小)将d代入,得b=2*(b*b/4-(sqrt(b*b/4+1)-1)*(sqrt(b*b/4+1)-1))/b;(就这样写误差还是比较小的,几乎跟内切法的精度一样),再化简得b=2*(b*b/4-(b*b/4+1)-1+2*sqrt(b*b/4+1))/b;(这个时候误差就大了,i只有49152),再化简b=2*(2*sqrt(b*b/4+1)-2)/b即b=2*(sqrt(b*b+4)-2)/b(误差依然比较大),所以断定d*d为误差所在
我的理解:无论如何,b,d等这些值是一定有偏差的,b=2*(b*b/4-d*d)/b=2*(b/2+d)*(b/2-d)/b,由于d进行了开根处理,误差微乎其微,几乎可以忽略不计,即可以当他们是常数,这个式子的误差级别y=ax+b(a,b为常量),b=2*(sqrt(b*b+4)-2)/b的误差级别y=a/x+b(a,b为常量),x在(0,1]区间显然后者的误差比较大

读书人网 >C语言

热点推荐