- 締切済み
floatの値について
初心者的質問です。暇な方お答え願います。 分かりやすく教えてくださると嬉しいです。 例えば、簡単な main() { float a; printf("値を入力して下さい ==> "); scanf("%f",&a); printf("入力した値は%fです",a); } という感じで値を入力して出力するプログラムがあったとします。 このとき,例えば値を 166.5と入力すれば、166.500000とでますが 166.7と入力すると、166.699997とでるのはなぜでしょうか? doubleで変数宣言した場合は、このようにならないのですが。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- inetd
- ベストアンサー率23% (43/184)
それは内部で2進数に変換して値を持っているからです。2進数に変換する理由はその方が計算が速いからです。しかしたとえば10進数の 0.1 を2進数に変換すると循環小数になってしまいます (0.0001100110011001100... という風に 1100 の連続になります。0.7の場合は0.10110011001100...で、やはり循環小数です)。つまり、0.1 非常に近い値ではあるけれど 0.1 ではない値ということです。printf() で出力するときは printf() 関数が内部でこの誤差を考慮して10進数として出力してくれるので 0.1 と出力されると思いますが、しかし内部では本当は違っているのです。 こういった10進数と2進数の問題があるので float よりも double の方が内部で保持しているビット数が多いため10進数変換時の誤差が少なくなります。(但しどんなCコンパイラでも sizeof(float) < sizeof(double) とは限りません。これは実装依存ですから同じこともあり得ます。お使いのコンパイラは float の方が double よりもビット数が少なかったためにそのようになったのだろうと思います)。
- ymmasayan
- ベストアンサー率30% (2593/8599)
多少、荒っぽい答えですが。 計算機が2進法なのはご存知ですね。 そこで、小数点以下の0.5と0.7に注目してみます。 0.5×2=1.0 ところが、0.7の小数点以下だけを2倍ずつしていくと 0.7×2=1.4 0.4×2=0.8 0.8×2=1.6 0.6×2=1.2 0.2×2=0.4 となって循環して一向に整数になってくれません。これは0.7が2進法の循環小数になっていることを表しています。つまり0.7は有限桁の2進小数では正確に表し切れないのです。 floatもdoubleも有効桁数が違うだけで本来的には元の数を表しきれないのですが、10進数に戻すときの丸め処理の関係で、doubleの方だけあたかもきちんと元の数を記憶しているように見えてしまうのです。