- ベストアンサー
for文について
教えてください double counter; for ( counter = 0 ; counter <= 5.0 ; counter = counter + 0.1 ) { printf("%f\n",counter ); } だと 5.000000 まで表示されますが、 for ( counter = 0 ; counter <= 4.0 ; counter = counter + 0.1 ) { printf("%f\n",counter ); } だと 3.900000 までしか表示されません なぜでしょうか? よろしくお願いいたします
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
ちょっと詳しく書いてみましょう。 既に回答にあるとおり、これは、浮動小数点の誤差による ものです。ただ、浮動小数点数に誤差はつきものですが、 必ず誤差が出る訳ではありません。 たとえば、整数値(小数点以下のないもの)は、double で、厳密に表現できます(ただし、10E15 あたりまで) また、小数点部分も、÷2を繰り返したもの 0.5 (= 1/2) 0.25 (= 1/2/2) 0.125 (= 1/2/2/2) および、その和 0.75 = 0.5 + 0.25 0.625 = 0.5 + 0.125 などは厳密に表現出来ます。 0.1 は、1/2/5 と、/5 という因数が出てくるので、 double ではうまく表現できません。 0.0001100110011.. という2進の無限小数となります。 さて、今回の場合、手もとにある処理系で計算してみると、 3.9 = 400 F 3333 3333 3338(16進表記) -> 3.8999....(10進表記) 4.0 = 401 0 0000 0000 0002 -> 4.000122 5.0 = 401 3 FFFF FFFF FFFE -> 4.9999... となります。 つまり、4.0 の時は、誤差の蓄積が、やや大きい側に 出てきたので、4.0 は表示されず、5.0 では、誤差が やや小さい側に出てきたので、5 まで表示されたとい うことになります。
その他の回答 (3)
- mtaka2
- ベストアンサー率73% (867/1179)
既に他の方がいろいろ書かれてますが、 丸め誤差について概念的に分かりやすく説明すると、以下のような例になります。 2/3 ずつ増やしたループで、 0 0.666666666666… 1.333333333333… 2 という4回ループを回すことを意図して、 for ( counter = 0 ; counter <= 2.0 ; counter = counter + 0.66667 ) { printf("%f\n",counter ); } といったループを組んだとします。 0.66666666666666666666666…と6が無限に続く小数は表現できませんから 途中で四捨五入してます。結果、このコードを実行すると、 0 0.66667 1.33334 となります。 ここからさらに0.66667を足すと2.00001になってループを抜けますから2は表示されません。 この場合は、10進数では3で割ったら割り切れないために、こういった誤差が発生したわけですが、同じ理屈で、 2進数では10で割ったら割り切れないため、見かけ上きりの良い数字である0.1を10回足しても、2進数で計算するコンピュータ内部ではきりが悪い演算で1にならない、ということが発生するのです。
- redfox63
- ベストアンサー率71% (1325/1856)
浮動小数点数で表現した場合に0.1が正確に表現できないので累積される誤差によりご質問のような現象が発生します for( counter = 0.0; counter < 50.0; counter += 1.0 ) { printf( "%lf\n", counter / 10.0 ); } for( counter = 0.0; counter <= 40.0; counter += 1.0 ) { printf( "%lf\n", counter / 10.0 ); } といった具合にして見ましょう 私ならdoubleでcounterは作成しません intまたはlongでカウンターを作ってdoubleで演算が必要な箇所を演算させます
- cortotbach
- ベストアンサー率44% (8/18)
浮動小数点は==で正確に評価できません。 http://ja.wikipedia.org/wiki/浮動小数点数 を参考にしてください。4.0という実数がdouble(8bytes)の変数では完全に表現できないことが分かるかと思います。
お礼
ありがとうございます
お礼
ありがとうございます 増分を利用したかったので上記のように書いてみたものの 結果は?ということです。