自然対数の底、eの値(改)

説明
僕個人は、新しい言語を習ったら練習問題みたいな感じで作るんだけど。手軽にぱっと見凝ったものが作れるので。多倍長計算の、基礎とは言わないけど簡単な部類。
アルゴリズム
普通のやり方。式は、
納n=0 - ∞](1/n!)
です。
特徴
何桁でもメモリの許す限り計算できます。普通じゃこうは行かない。100万桁求められました。220分ちょいでね。
/*****************************************************************************
                              eの値求めほーだい(Ver1.00)
                                                           programed by K.S.
*****************************************************************************/
#include <stdio.h>
#include <malloc.h>

#define K_MAX 10000  /* 何進数にするか 2とかでも意外にうまくいってうれしい */
#define E_MUL 10000  /* 連続した配列の数 実行時にうまくメモリを取れないので */
#define E_SUB 1              /* (K_MAX)進数 の配列を (E_MUL)*(E_SUB)個 取る */

#define E_MAX (E_SUB * E_MUL + 3)                           /* 計算用の配列 */

int main(void){
  int *ans[E_SUB+1];                              /* それまでの足し算の総和 */
  int *tmp[E_SUB+1];                                          /* 1/(count!) */
  int count = 1;              /* 今までに 1/(count!) を求めましたよってこと */
  int keta = 0;   /* 1/(count!) は K_MAX 進法で keta 桁目まで0ですよってこと*/
  int down;      /* 繰り下がり/上がりに使ってる 共用体使うべきなんだろうけど*/
  int print_count = 0;                           /* 画面に * を出すカウンタ */
  int i, j, k;                                                /* ループ変数 */
  FILE *fp;

  for(i=0; i<E_SUB; i++){                                     /* メモリ確保 */
    ans[i] = malloc(sizeof(int) * E_MUL);
    tmp[i] = malloc(sizeof(int) * E_MUL);
  }
  ans[E_SUB] = malloc(sizeof(int) * 3);
  tmp[E_SUB] = malloc(sizeof(int) * 3);                         /* ここまで */

  for(i=0; i<E_SUB; i++)                                    /* 数値の初期化 */
    for(j=0; j<E_MUL; j++)
      ans[i][j] = tmp[i][j] = 0;

  ans[0][0] = tmp[0][0] = 1;                                    /* ここまで */
  
  while(keta<E_MAX){                                        /* メインループ */
    down = 0;
    for(i=keta; i<E_MAX; i++){                         /* 1/(count!) の計算 */
      j = i / E_MUL; k = i % E_MUL;
      tmp[j][k] += down * K_MAX;
      down = tmp[j][k] % count;
      tmp[j][k] = tmp[j][k] / count;
      ans[j][k] += tmp[j][k];
    }

    down = 0;                                         /* 割った結果を足し算 */
    for(i=E_MAX-1; i>0; i--){
      j = i / E_MUL; k = i % E_MUL;
      ans[j][k] += down;
      down = ans[j][k] / K_MAX;
      ans[j][k] %= K_MAX;
    }
       /* どの桁まで0か計算してそれ以降の無駄な計算を省くと同時に進行の表示 */
    while(tmp[keta/E_MUL][keta%E_MUL] == 0 && keta < E_MAX){
      keta++;
      if(keta * 80 * 10 / E_MAX > print_count){
        print_count++;
        printf("*");
      }
    }
    count++;
  }                                                 /* メインループの終わり */

  fp = fopen("e.txt", "w");                             /* ファイルへの出力 */
  for(i=0; i<=E_SUB*E_MUL; i++){
    fprintf(fp, "%4d", ans[i/E_MUL][i%E_MUL]);          /* ここ何とかしたい */
                                    /* 常に4桁表示だし頭の0は表示されないし */
//  if(i % 20 == 0) fprintf(fp, "\n");                    /* 80字で改行する */
  }
  fclose(fp);
  
  for(i=0; i<=E_SUB; i++){                                  /* メモリの開放 */
    free(ans[i]);
    free(tmp[i]);
  }
  return 0;                                                     /* 正常終了 */
}

[戻る]