中华农历论坛知识讨论区历法知识 → 回复帖子

  回复帖子
用户名:   *您没有注册?
密码:   *忘记论坛密码?    标题采用“回复:XXX....”
主题标题:  *不得超过 200 个汉字
当前心情
上一页 发帖表情 下一页
内容
高级设置: 签名: 回帖通知:
 

主题最新回顾(发布时间:2011/6/18 15:22:00)
--  作者:秦汉昌
--  
 Machin公式


图片点击可在新窗口打开查看
图片点击可在新窗口打开查看


主题最新回顾(发布时间:2011/6/13 23:11:00)
--  作者:秦汉昌
--  

改为九位的原因是:单精度数最多表示十个十进制位,且高两位必需在27以内,所以,如果以十位为单元运算,就不能使用单精度数表示一个计算单元

 

  也就是说,想将百亿进制优化,改为十亿进制优化。


主题最新回顾(发布时间:2011/6/13 23:08:00)
--  作者:秦汉昌
--  

//PI计算javascript程序,Machin+百亿进制优化,2006.12 许剑伟 莆田十中

GJ2_machin={
 add:function(a,b,n){ //多精度a对多精度b的相加算法(小学加法)
  for(var i=n-1,f=0;i>=0;i--){
    a[i]+=b[i]+f;
    if(a[i]>=10000000000) a[i]-=10000000000,f=1; else f=0;
  }
 },
 sub0:function(a,b,r,n){ //多精度a对多精度b的相减算法(小学减法)
  for(var i=n-1,f=0;i>=0;i--){
    r[i]=a[i]-b[i]-f;
    if(r[i]<0) r[i]+=10000000000,f=1; else f=0;
  }
 },
 div:function(a,b,n){ //多精度a与单精度b相除算法(小学除法)
  for(var i=0,f=0,c;i<n;i++){
    c=a[i]+f*10000000000;
    a[i]=Math.floor((c+0.1)/b);
    f=c%b;
  }
 },
 dao:function(a,f,b,n){ //倒数(f/b)
  a[0]=Math.floor(f/b); f=f%b;
  for(var i=1,c;i<n;i++){
    c=f*10000000000;
    a[i]=Math.floor((c+0.1)/b);
    f=c%b;
  }
 },
 set:function(a,v,n){ for(var i=0;i<n;i++) a[i]=0; a[0]=v; a.length=n;}, //给数组置0并给首位置初值v
 //以下计算圆周率,计算公式:Machin PI=16arctg(1/5)-4arctg(1/239)
 a:new Array(),b:new Array(),c:new Array(), //三个工作数组,a存PI,b存arctg,c是临时数组
 arctg:function(k,v,zf,N){//求v*arctg(k),zf表示结果累加到a时的正负号
  var i=Math.round(N*23.1/Math.log(k*k)),n=i,n2;
  var a=this.a, b=this.b, c=this.c;
  for(;i>=0;i--){
    n2=Math.round((n-i)*N/n)+1; //末项计算位数控制
    if(n2>N) n2=N;
    this.dao(c, v,2*i+1,n2);
    this.div(b, k*k,n2);
    this.sub0(c,b,b,n2);
  }
  this.div(b,k,N);
  if(zf>0) this.add(a,b,N);
  else     this.sub0(a,b,a,N);
 },
 pi:function(){ //本程序所得最后5位可能有错
   var N=GJ2_N.value-0; N=floor(N/10+1.5); //N为计算的位数
   var a=this.a, b=this.b; this.set(a,0,N); this.set(b,0,N); //PI结果数组及arctg数组,初值置0
   this.arctg(5,16,1,N);
   this.arctg(239,4,-1,N);
   a[0]='<br>';
   for(var i=1;i<N;i++){
    a[i]=String(10000000000+a[i]).substr(1,10); //补足10位
    if(i%10==0) a[i]+='<br>'; else a[i]+=' ';
   }
   GJ2_out.innerHTML= '基于Machin公式,并做百亿进制优化,速度较快。<br>'
     +'计算公式:Machin PI=16arctg(1/5)-4arctg(1/239)<br>'
     +'最后5位可能有错:<font color=red>PI=3.'+a.join('')+'</font>';
 }
};

 

这段程序中,多精度数以十个十进制位(即十亿)为一个单元进行计算的,我想改为以九位十进制数为一个单元时行多精度运算,不知道需要作什么改动,如果不作发运,不知对arctg的结果有没有影响


主题最新回顾(发布时间:2011/6/13 20:53:00)
--  作者:浪-淘-沙
--  
以下是引用秦汉昌在2011-6-13 20:06:00的发言:

呵呵,是我理解错了

程序的执行必须有精确的验证结果

我只是简单的估算了一下,导致认识上的错误

 

现在,汉编程序也调试好了

 

不知精确否,计算结果如下:

 

本算法为低速算法,计算位数不宜过大,否则计算时间太长。
以下计算圆周率,计算公式:PI/2=1+1/3+1*2/(1*3*5)+1*2*3/(1*3*5*7)+...
通过提取公因子得连分式形式:PI=2+1/3(2+2/5(2+3/7(2+...,这样只需迭代计算a=2+a*n/(2n+1),n=N,…3,,2,1即可得到a=PI
最后5位可能有错: 3.
1415926535  8979323846  2643383279  5028841971  6939937510  5820974944  5923078164  0628620899  8628034825  3421170679 

恭喜你。

 

我刚才用JAVASCRIPT调试,将每次循环的中间变量都打印出来,没有出现你所说的疑问。

幸好你自己能够解决。


主题最新回顾(发布时间:2011/6/13 20:09:00)
--  作者:秦汉昌
--  

呵呵,谢谢浪版给予耐心指导

 

原来,在设计时,将外循环多做了一次,即i=0的情况也迭代进去了,导致最终结果为0,而我却没有从外循环上思考,尽想着内循环的代数式的问题


主题最新回顾(发布时间:2011/6/13 20:06:00)
--  作者:秦汉昌
--  

呵呵,是我理解错了

程序的执行必须有精确的验证结果

我只是简单的估算了一下,导致认识上的错误

 

现在,汉编程序也调试好了

 

不知精确否,计算结果如下:

 

本算法为低速算法,计算位数不宜过大,否则计算时间太长。
以下计算圆周率,计算公式:PI/2=1+1/3+1*2/(1*3*5)+1*2*3/(1*3*5*7)+...
通过提取公因子得连分式形式:PI=2+1/3(2+2/5(2+3/7(2+...,这样只需迭代计算a=2+a*n/(2n+1),n=N,…3,,2,1即可得到a=PI
最后5位可能有错: 3.
1415926535  8979323846  2643383279  5028841971  6939937510  5820974944  5923078164  0628620899  8628034825  3421170679 


主题最新回顾(发布时间:2011/6/13 19:28:00)
--  作者:浪-淘-沙
--  
以下是引用秦汉昌在2011-6-13 18:06:00的发言:

这两个算式,能明白,即求余数和商,除法运算,从左至右,余数f*10与右位相加继续运算

 

  问题是: f = a[j]*i+f*10;

 

令N=N+1=101,所以,i=343, b=687

 

当第一次外循环时,i=343, b=687,a[0]=0

   内循环   当j=0时,a0=0,  f=0  ,第一轮内循环对数组a无影响

 

第二次外循环时,i=342, b=685,a[0]=2

 

 第一次内循环:  f=0,    f=a[0]*i+f*10=2*342+0*10=684<b

                      这时:a[0]=floor(f/b)=0

                       在以后所有的第一次内循环中,f=a[0]*i+f*10<b都会成立

 

                    我就想不通,程序是怎么得出整数商的

 

                  外循环将a[0]l累加2,由于被除数小于除数,所以内循环又将其置0,如此循环.....

内循环   当j=0时,a0=0,  f=0  ,第一轮内循环对数组a无影响

 

什么叫嵌套循环?

就是外循环i=343时,内循环j 从0一直到101,共做101次的计算,每次计算,都对数组a[j]进行赋值。

怎么你却理解成对数组无影响?

 

*******************************

for(;i>0; i--,b-=2,a[0]+=2) //每计算3.4次得到1位十进制精度
  for(j=0,f=0;j<N;j++){      //多精度a与单精度b相除算法(小学除法),分子i,分母2*i+1
    f = a[j]*i+f*10;
    a[j] = Math.floor(f/b);
    f %= b;
  }
****************

就以你给的数字为例:

令N=N+1=101,所以,i=343, b=687

当第一次外循环时,i=343, b=687,a[0]=0

   内循环   当j=0时,a0=0,  f=0   


主题最新回顾(发布时间:2011/6/13 18:06:00)
--  作者:秦汉昌
--  
以下是引用浪-淘-沙在2011-6-13 17:17:00的发言:

首先你要相信,原作者那个程序是可以正常运行的,即可以计算出“圆周率”的。

那么你为何认为循环无效呢?

如果真的如你所说循环无效,那原程序又如何计算出圆周率。

 

然后,下面这二个语句,你是否真的看明白了?

a[j] = Math.floor(f/b);
    f %= b;//这是求余数运算啊。比如f=20,b=15,则f %= b结果是f=5.

这两个算式,能明白,即求余数和商,除法运算,从左至右,余数f*10与右位相加继续运算

 

  问题是: f = a[j]*i+f*10;

 

令N=N+1=101,所以,i=343, b=687

 

当第一次外循环时,i=343, b=687,a[0]=0

   内循环   当j=0时,a0=0,  f=0  ,第一轮内循环对数组a无影响

 

第二次外循环时,i=342, b=685,a[0]=2

 

 第一次内循环:  f=0,    f=a[0]*i+f*10=2*342+0*10=684<b

                      这时:a[0]=floor(f/b)=0

                       在以后所有的第一次内循环中,f=a[0]*i+f*10<b都会成立

 

                    我就想不通,程序是怎么得出整数商的

 

                  外循环将a[0]l累加2,由于被除数小于除数,所以内循环又将其置0,如此循环.....


主题最新回顾(发布时间:2011/6/13 17:23:00)
--  作者:浪-淘-沙
--  

 

  呵呵,浪版,可以这个程序的算法给我讲解一下吗

 

你需要做的是:找一本“JAVASCRIPT”参考书,或者“C语言”的参考书,粗略学习一下“英文”编程的原理。

 

原作者的PI代码,本身并不难理解。

一行行看下去,for循环一点都没你所说的“无效循环”。


主题最新回顾(发布时间:2011/6/13 17:20:00)
--  作者:浪-淘-沙
--  

      在下一次循环中,由于f被 重新赋0值,所以,与第二次循环的运行结果一样,以此类推,这个循环嵌套无意义。

 

 

呵呵,请高手指点,我这样分析,正确否?

我觉得你还是没明白for循环的原理啊。

什么叫下一次循环中,f被重赋值啊?

 

for循环中,第一个分号“;”之前的语句,在循环中只执行一次啊。难道你理解成它每次都要执行的?