πを16進数で求める
(C)裏目小僧
(戻る)

16進数で、多倍長(多桁)計算を使わずに、円周率πを多桁求めます。
JavaScriptでは=
ご覧の通り、あまり高速ではありません。
10進にするなら、どうしても多倍長処理が必要なようです。

使用してる公式については

http://www.pluto.ai.kyutech.ac.jp/plt/matumoto/pi_small/node9.html



ここに10進多倍長計算による私の所よりずっと高速なπ計算JavaScriptがあります

http://www.ecs.cst.nihon-u.ac.jp/~hiroshi/JavaScript/pi.html




{32bit delphi版です。
 コンソールアプリとして    Dcc32 -CC PiHex.pas で作成します。
   フリーパスカルなら      PPC386    PiHex.pas です。
}
program PiHex;
uses SysUtils,math;
{ 割り算  ( (16^n)*b/x) mod (2^32)  }
function DivM(n,b0,x:Cardinal; f:integer; var fraction:Extended):Cardinal;
var n0:Cardinal;
var a:Cardinal;
var b:Cardinal;
var l:Cardinal;
begin
 n0:=n;
 a:=0;
 b:=b0;
 l:=0;
 n:=n0*4;
while( (n>=1) and ((x and 1)=0) ) do
begin
 dec(n);
  x := x shr 1;
end;

while(n>=1) do
 begin
  a := a shl 1;
  b := b shl 1;
  while(b>=x) do  begin a:=a+1 ; b:=b-x;end;
  dec(n);
  inc(l);
  if(b=b0)then 
   begin
    if(l>=32)then
      begin
      n:=n mod l;
      end;
   end;
 end;
 while(b>=x) do  begin a:=a+1 ; b:=b-x;end;
 DivM:= a;
 if f <0 then  fraction := fraction - int(b)/x  { 少数点以下 }
      else    fraction := fraction + int(b)/x; { 少数点以下 }
 
end;

{π= Σ (4/(8*k+1)-1/(4*k+2)-1/(8*k+5)-1/(8*k+6))/(16^k) }
function Pis(n:integer) : Cardinal;
var s:Cardinal;
var k:integer;
var fr:Extended;
begin
 s :=0;
 fr:=0;
 for k:=0 to n do 
 begin
  s:=s +DivM( n-k,4,8*k+1, 1,fr);
  s:=s -DivM( n-k,1,4*k+2,-1,fr);
  s:=s -DivM( n-k,1,8*k+5,-1,fr);
  s:=s -DivM( n-k,1,8*k+6,-1,fr);
  while fr >=1 do  {小数点以下の累積結果を小数点以上に反映}
   begin
    fr := fr - 1;
    s  := s  + 1;
   end;
  while fr <0  do 
   begin
    fr := fr + 1;
    s  := s  - 1;
   end;
 end;
 Pis:=s;
end;
procedure PisPrint ;
var i,j:integer;
var s1,s2:Cardinal;
begin
writeln('3.');
 for i:=1 to 10000000 do
 begin
  j:=i*4;
  s1:=Pis(j+4) shr 16;  {4桁ずらして求めて、同じかどうか比較 }
  s2:=Pis(j  ) and $ffff;
  if s1 = s2   then   write(IntToHex(s1,4))
    else break;
write(' ');
 end;
end;


begin
PisPrint;
end.


#include <stdio.h>
/* πを16進で求める */
/* 割り算  ( (16^n)*b/x) % (2^32)  */
unsigned  DivM(unsigned n0,unsigned b0,unsigned x,int f,long double *fraction )
{ 
   unsigned a =0;
   unsigned b =b0;
   unsigned l =0;
   unsigned n =n0*4;
   while( (n>=1) && ((x & 1)==0) )  { --n; x >>= 1; };
   while(n>=1)
   { 
     a <<= 1u; 
     b <<= 1u;
      l++;
      n--;
   if( b >= x ){ do { ++(a) ;  b -= x;} while( b >= x );
     if(b==b0)
      {
       if(l>=32) n = n % l;
      }
     } 
  }
 if(b>=x) { a=a+b/x ; b=b % x;}
 if(f <0 )   (*fraction) -=( (long double) b / (long double)x);
    else     (*fraction) +=( (long double) b / (long double)x); 
  return  a;
}

/*π= Σ (4/(8*k+1)-1/(4*k+2)-1/(8*k+5)-1/(8*k+6))/(16^k) */
unsigned Pis(int n)
{
int k;
unsigned s;
long double fr;
 s =0;
 fr=0;
 for(k=0 ;k<= n;k++)
 {
  s=s +DivM( n-k,4,8*k+1, 1,&fr);
  s=s -DivM( n-k,1,4*k+2,-1,&fr);
  s=s -DivM( n-k,1,8*k+5,-1,&fr);
  s=s -DivM( n-k,1,8*k+6,-1,&fr);
  while( fr >=1 )  /* 小数点以下の累積結果を小数点以上に反映 */
   {
    fr = fr - 1;
    s  = s  + 1;
   }
  while( fr <0  ) 
   {
    fr = fr + 1;
    s  = s  - 1;
   }
 }
 return s;
}

void PisPrint()
{
int i,j;
unsigned s1,s2;
 printf("%s\n","3.");
 for (i=1 ; i<10000000 ;i++)
 {
  j=i*4;
  s1=Pis(j+4) >> 16u;  /*4桁ずらして求めて、同じかどうか比較 */
  s2=Pis(j  ) &  0xffff;
  if( s1 == s2 )   printf("%04X ",s1) ;
    else break;
 }
}
main()
{
 PisPrint();
 return 0;
}

おまけで、多倍長10進でπを求める例
pascalコードはあまり見かけないので
program pai;
uses SysUtils;
///////////////////////////////
//2000 桁くらのπの計算
//ppc386  -So wpi.pas
//dcc32   -CC wpi.pas

const _N100 = 100; //1000でもOK
type wlong = array[0..1003] of smallint;
/////////////////////////////////////
// 結果の印刷
procedure wprint(var d:wlong ; gd:integer);
var i:integer;
var s:string;
begin
 for i:=low(d) to high(d)-gd do
 begin
 if _N100 = 100 then  s:=format('%2d',[d[i]])
 else if _N100 = 1000 then  s:=format('%3d',[d[i]])
 else if _N100 = 10000 then  s:=format('%4d',[d[i]]);

  if i<>low(d) then
 if s[1]=' 'then 
   begin s[1]:='0'; if s[2]=' 'then 
     begin s[2]:='0';
        if s[3]=' 'then s[3]:='0';
     end;
   end;
    write (s);
  if i=0 then write( '.');
 end;
 writeln;
end;

/////////////////////////////////////
// ゼロクリア
procedure w0(var a:wlong);
var i:integer;
begin
 for i:=high(a) downto low(a) do  a[i]:=0;
end; 

/////////////////////////////////////
// 正規化
procedure wc(var a:wlong);
var r,w:integer;
var i:integer;
begin
 r:=0;
 for i:=high(a) downto low(a) +1 do
 begin
   w :=a[i]+r; r:=0;
  while(w<0  ) do begin w:=w+_N100; r:=r-1;end;
  while(w>_N100) do begin w:=w-_N100; r:=r+1;end;
  a[i]:=w;
 end; 
end; 

/////////////////////////////////////
//  割算 a = a / b
function wdiv(var a:wlong; b:integer):boolean;
var r,w:integer;
var i:integer;
begin
  r:=0;
 result:=true;
 for i:=low(a) to high(a) do
 begin
  w:=a[i]+r;
  a[i]:= w div b;
  result:=result and ( a[i]=0 ) ;//全てがゼロになったか
  r:= w mod b;
  r:= r * _N100;
 end; 
 wc(a);
end;

/////////////////////////////////////
//  割算の和 sum =sum + a / b
procedure wdivsum(var sum:wlong;var a:wlong; b:integer);
var r,w:integer;
var i:integer;
begin
  r:=0;
 for i:=low(a) to high(a) do
 begin
  w:=a[i]+r;
  sum[i]:= sum[i]+(w div b);
  r:= w mod b;
  r:= r * _N100;
 end; 
 wc(sum);
end;

/////////////////////////////////////
//  マチンの公式でπを求める
var a5  :wlong;
var a239:wlong;
var xwpi:wlong;
procedure wwpi;
var k:integer;
begin

  w0(xwpi);
  w0(a5);
  w0(a239);
 a5[0]:=16;   // 16* arctan(1/5)
  k:=1;
 repeat
   wdiv(a5,5); 
   wdivsum( xwpi , a5,k);
   wdiv(a5,5); 
   wdiv(a5,5);
   k:=k+2;
   wdivsum(xwpi, a5 ,-k);
   k:=k+2;
 until  wdiv(a5,5); 

 k:=1;
 a239[0]:=4; // 4* -arctan(1/239)
 repeat
    wdiv(a239,239); //*x
    wdivsum( xwpi , a239,-k);
    wdiv(a239,239); //*x
    wdiv(a239,239); //*x
    k:=k+2;
    wdivsum(xwpi, a239 ,k);
    k:=k+2;
 until  wdiv(a239,239); //*x

end;

/////////////////////////////////////
//  計算時間を測定
const  kernel32  = 'kernel32.dll';
function GetTickCount:Cardinal; external kernel32 name 'GetTickCount';
var t0:Cardinal;
var t1:Cardinal;
var t2:Cardinal;
begin
 t0:=GetTickCount;
 wwpi;
 t1:=GetTickCount;
 wprint(xwpi,3);
 t2:=GetTickCount;

writeln('exec  time=', t1-t0,'ms');
writeln('print time=', t2-t1,'ms');
writeln('total time=', t2-t0,'ms');
end.
java によるπ

http://www.matsusaka-u.ac.jp/~okumura/java/keisan-big.html

c によるπ

http://www.nara-edu.ac.jp/~asait/visual_c/sample0/pi.htm

c によるπ(プログラム入門編)

http://www.first.tsukuba.ac.jp/~yuya/mathematics/pi/index-j.html

C インラインアセンブラ

http://www.osk.3web.ne.jp/~akasaki/