- ベストアンサー
C言語で組み合わせの問題を解く方法とは?
- C言語で組み合わせの問題を解く方法を説明します。
- 入力した値が一定以上の場合、組み合わせの計算結果が狂う現象が起こることがあります。
- この現象の原因と対策について解説します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
この方法で、この環境だと、n=30, k=14 までは正しく求めることができます。 30C14=145,422,675に(30-15+1)=16を掛けると、intで取り扱うことができる最大の数値(2の31乗よりも1小さい値:2,147,483,647)よりも大きくなってしまいます(オーバーフローです)。以降は正しくないnckの値を使って次の値を求めているので当然正しい値は得られません。 #1の回答の「(n-k+1)/kは恒に整数か?」は何を指摘されているのかわかりません。nck*(n-k+1)は、オーバーフローしない限り、kで割り切れます。 また、「nckの最大値は?」については、n≦33であればnCkの値がintの最大値を超えることはありません。
その他の回答 (3)
- hanabutako
- ベストアンサー率54% (492/895)
integer overflowです。 正しい結果がほしいなら、gmpなどを使うことを検討すると良いかもしれません。 http://gmplib.org/ 参考までに、こんな感じに書き換えられます。 gmpのライブラリーとリンクしてください。 #include <gmp.h> #include <stdio.h> void print_nck(unsigned long k, mpz_t nck) { char* nck_str; nck_str = mpz_get_str(NULL, 10, nck); printf("%12lu\t%s\n", k, nck_str); free(nck_str); } int main(void) { unsigned long n, k; mpz_t nck; printf("n = "); scanf("%lu", &n); printf(" k nCk\n"); k = 0; mpz_init_set_ui(nck, 1UL); print_nck(k, nck); for (k = 1; k <= n; k++) { mpz_mul_ui(nck, nck, (n - k + 1)); mpz_fdiv_q_ui(nck, nck, k); print_nck(k, nck); } return 0; }
お礼
ありがとうございます. 参考にさせて頂きますね.
- Tacosan
- ベストアンサー率23% (3656/15482)
この場合 #1 の最初の指摘は外れ. それ以外はあってるんだけどね.
お礼
左優先であることをすっかり忘れていました. 計算式の途中でintの範囲を超えていることに気づきました. ご指摘ありがとうございました.
- TooManyBugs
- ベストアンサー率27% (1472/5321)
(n-k+1)/kは恒に整数か? intはどのような変数か? nckの最大値は? いずれも基礎中の基礎。
お礼
ご指摘ありがとうございました.
お礼
ご丁寧にありがとうございます. 電卓を取り出して確認していたらnckを求める式の途中でintの範囲を超えていることに気づきました. そうこうしていると皆さんへのお礼が遅くなりました, 申し訳ないです. 今回はakayoroshiさんの回答を見ることで自分の考えが正しいのかどうかが確認できましたのでベストアンサーとさせて頂きました. 回答して頂いた皆さん, あらためてありがとうございました. これでスッキリして眠れます...