以下のような、順列nPrと組み合わせnCrを、n、rを0~100の範囲で変化させて計算して結果をCSVファイルに出力するプログラムを、C言語で作成してみました。
該当のソースコード
C言語
1#include <stdio.h> 2#include <stdlib.h> 3 4void procedure(int i); 5unsigned long long int permutation(int n, int r); 6unsigned long long int combination(int n, int r); 7 8int main(void) 9{ 10 int i; 11 12 for (i = 0; i < 2; i++) 13 procedure(i); 14 15 return EXIT_SUCCESS; 16} 17 18void procedure(int i) 19{ 20 int j, k; 21 FILE *fp1, *fp2; 22 unsigned long long int ans; 23 24 switch (i) { 25 case 0: 26 fp1 = fopen("output1.csv", "a"); 27 if (fp1 == NULL) { 28 printf("ファイルを開けません。処理を中断します。\n"); 29 return; 30 } 31 for (j = 0; j <= 100; j++) 32 for (k = 0; k <= j; k++) { 33 ans = permutation(j, k); 34 fprintf(fp1, "%dP%d,%llu\n", j, k, ans); 35 } 36 fclose(fp1); 37 break; 38 case 1: 39 fp2 = fopen("output2.csv", "a"); 40 if (fp2 == NULL) { 41 printf("ファイルを開けません。処理を中断します。\n"); 42 return; 43 } 44 for (j = 0; j <= 100; j++) 45 for (k = 0; k <= j; k++) { 46 ans = combination(j, k); 47 fprintf(fp2, "%dC%d,%llu\n", j, k, ans); 48 } 49 fclose(fp2); 50 break; 51 default: 52 break; 53 } 54} 55 56/* 順列 */ 57unsigned long long int permutation(int n, int r) 58{ 59 int i; 60 unsigned long long int ans = 1; 61 62 if ((n == 0) || (r == 0)) 63 ; 64 else 65 for (i = 0; i < r; i++) 66 ans *= (n - i); 67 68 return ans; 69} 70 71/* 組み合わせ */ 72unsigned long long int combination(int n, int r) 73{ 74 int i; 75 unsigned long long int ans = 1; 76 77 if (r > n - r) 78 r = n - r; 79 80 if ((n == 0) || (r == 0)) 81 ; 82 else 83 for (i = 1; i <= r; i++) { 84 ans *= (n - r + i); 85 ans /= i; 86 } 87 88 return ans; 89}
結果、当然と言えば当然ですが、大きな数値に対しては、出力がおかしくなりました。値のオーバーフローによるものだと思います。
エクセルのPERMUT関数とCOMBIN関数の結果と照合している途中に気付き、少し調べてみたら、エクセルでは
「値がある程度大きくなったら、『●●E▲▲』(●●掛ける10の▲▲乗)の形で出力し、エクセルの処理できる正の最大値9.99999999999999E+307を超えたら、#NUM!と出力する」
ことが分かりました。
そこで、エクセルとは値の範囲が異なりますが、エクセルに似たことができるように改変したいのですが、どのように変えればよいか、見当が付きません。
実際に、「60種のうちから5種を選ぶ組み合わせ(60C5)」を計算する必要があり(計算結果は5,461,512通り)、実用に耐えるものを作りたい、というのが、そもそもの作成動機です。
お助けください。

回答3件
あなたの回答
tips
プレビュー