電子書籍の厳選無料作品が豊富!

こんにちは
私は日本でプログラミング勉強している外国人です。
わからない問題が有るのでここに載せます。
よろしくお願いいたします。

#include<stdio.h>

void main(void)
{
float a;

for(a=0.0; a <= 1.0; a +=0.1)
{
printf("%f\n",a);
}

printf("%f\n",a);
}

上の問題ですが出力すれば0.000000から1.000000まで
表示されます。でも最後のprintf文を消す時に
0.000000から0.900000まで表示されます。

その前に
for文のことなんですが、私は「a<=1.0」も書き入れました。

どうして1.000000の数値が画面に表示されないか分かりません。

手伝っていただけませんか。



ps。日本語がまだ不足なので何かおかしい部分があります。
申し訳ありませんが、間違った部分があれば直していただきたいんですがよろしいですか。

お願いいたします。

A 回答 (6件)

★『float』や『double』型は誤差に注意して下さい。


・おそらく、0.900000 の次に 0.1 を加えると 1.000000001 となっていると思います。
 つまり、内部では 0.100000001 という値が加算された状態になってしまい、比較すると
 『1.000000001 <= 1.000000000』は『偽』となるために最後の『1.000000』の数値だけが
 表示されなかったと思います。

原因:
・浮動小数点は『小数』以下を正しく表現できないのです。
 理由は 2 進数で小数点以下も表現しようと無理やり(そいうルール)で小数を扱いますので
 場合によっては正確にならないのです。
・たとえば、『10÷3×3』は数学的には『10』に戻りますが、コンピュータの世界では誤差
 から『9.99999998』などとなる場合があるのです。数学とはちょっと違います。
・このため、『float』型や『double』型を利用する際には、誤差に注意してのプログラミング
 が必要になります。
・今回は for 文の最後に『1.000000』が表示されるため、ここの部分を削除すると『0.900000』
 までしか表示されなかったと思います。

余談:
・私は日本人ですが、いまだにちょっと文章がおかしい時があります。むかし、国語が苦手でしたので。
・質問者さんは『外国人』のようですが、変換間違いもなく日常会話(文章)は問題はないと思います。
・以上。おわり。→浮動小数点は『誤差』に注意して下さい。
    • good
    • 0
この回答へのお礼

本当にありがとうございます。
答えを見た時すごいだと思ってきました。

また私の日本語についての部分のお話もありがとうございます。

お礼日時:2007/03/19 09:43

浮動小数点数は多くの場合、内部的には2進数を使っています。

その結果、0.1という値は実際には0.1より少し大きな値として扱われます。ですから、a <= 1.0の部分で、11回目(1.0と等しくなることを期待している回)では、実際にはaは1.0より少し大きいために条件が偽になってしまいます。

また、float型からdouble型に変換する際にも誤差を増大させています。double型ではじめから0.1と記述するより、いったんfloat型の変数に格納してからdouble型に変換する方が、同じ0.1のつもりでもより大きくなります。

ところで、全然違う話ですが、main関数の返却値型はint型にすべきです。void型を許している処理系もありますが、その場合は使用されている処理系を特定しなければ、何が起こってもしかたがないという結論になります。
# ちなみに私が使っている処理系では、質問者さんのコードは警告が出ますし、コンパイルオプション次第ではエラーになります。
    • good
    • 0
この回答へのお礼

質問について細かく説明させてありがとうございました。

お礼日時:2007/03/19 09:52

浮動小数点数を扱うときには、他の方も書かれているように


十分注意する必要があります。
特に == による比較などは行ってはいけません。

日本語ですが
浮動小数点演算について
http://docs.sun.com/source/806-4847/ncg_goldberg …

という文書に、事細かに解説があります。

bradforyou さんの native languageが何かは
わかりませんが、
日本語に翻訳される前の元の論文が
What Every Computer Scientist Should Know About Floating-Point Arithmetic
http://docs.sun.com/source/806-3568/ncg_goldberg …

で読めます。
参考になるとよいのですが。
    • good
    • 0
この回答へのお礼

質問について原理部分がいい勉強になりました。
日本語の部分についてもいいホームページを紹介させてあれがとうございます。 私は韓国人です。

お礼日時:2007/03/19 09:50

#3です、プログラムに間違いがありました、訂正します。



#include<stdio.h>

void main(void)
{
float a;

for(a=0.0; a <= 1.0; a +=0.1)
{
printf("%18.15f\n",a);
}

printf("%18.15f\n",a);

}
    • good
    • 0

このブログラムを実行してください。

原因がよく分かります。

#include<stdio.h>

void main(void)
{
float a;

for(a=0.0; a <= 1.0; a +=0.1)
{
printf("%1.15f\n",a);
}

printf("%1.15f\n",a);
}
    • good
    • 0
この回答へのお礼

そのままでして確認できました。しかも二回も答えさせてありがとうございます。
でもなぜするかについての部分も私のとって大事な部分ですので
すみません。でもいい勉強になりました。

お礼日時:2007/03/19 09:48

floatの演算には誤差があるために、0.1を10回加えても1.0にはなりません。


したがって a == 1.0 がTRUEになることはなく、
a <= 1.0 は a < 1.0 と同じ意味になってしまいます。
    • good
    • 0
この回答へのお礼

内容は簡単でしたが理解することも簡単に出来てうれしかったです。
でもいい質問を選ぶのが一つだけで残念でした。

でも答えありがとうございます。

お礼日時:2007/03/19 09:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報