• ベストアンサー

(プログラムがあるため長文です)次の2つの違いは?

C言語(VisualStudio.net2003)で組み合わせに関するプログラムを作成したのですが、(1)の式で、プログラムを実行させると、違う結果が出てしまい、(2)の式で実行させると、正しい結果が出ます。 (1)(コピーして、確認(実行)してみてください) #include <stdio.h> int main ( void ) { int n,r,k; int a=1; printf("n=?");scanf("%d",&n); printf("r=?");scanf("%d",&r); for ( k=1 ; k<=r ; k++){ a *= (n-k+1)/k; printf("a%d=%d\n",k,a); } return 0; } (2)a *= (n-k+1)/k; の部分を a = a*(n-k+1)/k; に変更する。 a *= (n-k+1)/k;という式が、a = a*(n-k+1)/k;ということを意味しているので、どちらでも正しい結果がでる気がするのですが、なぜ(1)では正しく結果が表示されないのでしょうか?教えてください。 また、(1)のような *= をつかってプログラムを組みたいとき、a *= (n-k+1)/k; をどのように変更すればよいのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

(1)のとき、まず (n-k+1)/k を計算(※)してから、 その結果を a に掛けています。つまり、 a = a * ((n-k+1)/k); と同じことをしています。このとき、(※)の整数どうしの割り算で、 ちょうど割り切れる場合もありますが、 小数点以下の端数が出て、それを切り捨てる場合もあります。 後者の場合、a の最終的な値は正しくなくなってしまいます。 *= 演算子を使ってこれを防ぐには、例えば a *= n - k + 1; a /= k; のようにする必要がありそうです。ただ、この場合、n と k の値によっては 最初の掛け算のところでオーバーフローするおそれがあります。 掛け算の結果が int型で扱える範囲に収まっている限りは大丈夫です。

hyper1234
質問者

お礼

解答ありがとうございます。 a *= n - k + 1; a /= k; としたら正しい結果になりました。 また、型キャストで、a *= double(n-k+1)/double(k);としても、きちんとした結果が得られました。 ということは、コンピュータが行った計算結果は正しいが、型が違うため、その値を表示できなかったということですね・・・ 今回の質問をして、同じ結果を表すものでもいろいろなプログラムの書き方があることを知りました。 もし、また分からないことがあったときにはよろしくお願いします。

その他の回答 (1)

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

変数 a が int 型のため、(n-k+1)/k が整数にまるめられてから a にかけ算されるのと、a*(n-k+1)/k が整数にまるめられた結果が異なるのでしょう。

hyper1234
質問者

お礼

早速の解答ありがとうございます。 型キャストで、a *= double(n-k+1)/double(k);としたところ、きちんとした結果が得られました。 ということは、コンピュータが行った計算結果は正しいが、型が違うため、その値を表示できなかったということですね・・・ もし、また分からないことがあったときにはよろしくお願いします。

関連するQ&A