いちばん失敗した人決定戦

float型変数の値代入と表示について質問があります。

#include <stdio.h>

int main(void)
{
 float flVal = 50.456;
 printf("float型変数:%f", flVal);
 return 0;
}

上記を実行すると、「float型変数:50.456001」と表示されました。
また、float flVal = 50.1; と変えて実行すると、「float型変数:50.099998」と表示されました。

それぞれ期待していた結果は、
「float型変数:50.456000」、「float型変数:50.100000」だったのですが
代入した値と結果が微妙に異なる理由は何でしょうか。よろしくお願いします。

A 回答 (4件)

IBMのページから


http://www-06.ibm.com/jp/domino04/lotus/support/ …
基本的に小数点以下の数値を含むものは(0.5,0.25、0.125などを除き)、誤差が生じるため。

実際の浮動小数点演算プログラムでは、許容できる範囲であれば一致しているとみなして処理を行うことが多い。

irb(rubyの対話型インタプリタ)やpythonのプロンプトで
irb> 0.1 +0.2 == 0.3 (Enter) とすると
falseが返る。

金額計算などでは単位未満(日本での銭単位とか)を扱う場合はこれでは困るので、小数点以下でも有効桁数内では誤差が生じない固定小数点型が用いられる。

COBOLが何のかんのと言われながら、勘定系取引でシェアが高かったのも基本が固定小数点型を採用していた事が大きい

SQLでも整数型、浮動小数点型、固定小数点型みんなあります。
(Oracleは長いこと、固定小数点型で全部こなしてましたが)

JavaではBigDecimalクラスが固定小数点です。ただ、Java演算子のオーバーロードが出来ないので、いちいちadd、sub、multiply、divideメソッドを使わなければならないのがちょっと面倒。

.Net Framwork( VB.NET、C# )のdecimalクラスの方が直感的かもしれない。

ちなみにrubyにもあります。
http://www.ruby-lang.org/ja/man/html/BigDecimal. …
    • good
    • 0
この回答へのお礼

詳しい解説ありがとうございます。
float型が内部的に2進数でどのように保存されているか、
2進数から10進数にどのように変換される過程で誤差が発生するのか、勉強したいと思います。

また、データ型として固定小数点型という考え方があること、
C言語以外では固定小数点型をどのように扱うかの情報まで教えていただき、
ありがとうございました。参考にさせていただきます。

お礼日時:2011/03/05 15:55

あとは、printfのような可変引数の場合、floatはdoubleに変換されます。


%fもdoubleを対象にしています。
例えば、
doubleでは50.456+誤差0.0000000000001
floatでは 50.456+誤差0.000001
だったとします。
%fではdoubleの分の誤差はまるめこんで 50.456と表示します。
floatでは誤差まで含めた50.456001がdouble型として変換されて、%fで処理されます。0.000001はdoubleでは有効桁内なので%fでは表示まるめこまないで表示します。(正確には、doubleの有効桁のところでのまるめこみが行われます)

特に理由が無い場合はdoubleを使うようにしましょう。
    • good
    • 0
この回答へのお礼

回答いただき、ありがとうございます。

double型で試したところ、
50.1は「50.100000」、50.456は「50.456000」と結果表示されることを確認しました。
floatとdoubleで有効桁が異なるため丸め込みの桁数が変わり、
結果も異なることが理解できました。
ありがとうございます。

お礼日時:2011/03/05 17:50

簡単に言うと誤差です。



float flVal = 50.1;

とすると、float 型の値として 50.1 に最も近い 50.456001 が代入されたのだと思います。

↓を読むと納得できると思います。
http://pc.nikkeibp.co.jp/pc21/special/gosa/eg4.s …

あと、参考までに
http://ja.wikipedia.org/wiki/%E6%B5%AE%E5%8B%95% …
    • good
    • 0
この回答へのお礼

回答いただき、ありがとございます。

紹介していただいた日経のページに、
丁寧に解説が載っていましたのでじっくり読ませていただき、理解できました。
ありがとうございました。

お礼日時:2011/03/05 17:39

特殊なものを除くと、floatは二進数です。


なので、10進数ではきれいに表せる数字であってもきれいに表現できない場合があります。
少なくとも有限の桁数なら誤差が発生します。

それが困る場合は内部的に10進数の計算を使えるするものもありますが、一般的ではありません。

とりあえず、コンピュータで実数を使う場合はそのようなことが発生するというのは覚えておく必要があります。
    • good
    • 0
この回答へのお礼

回答をいただき、ありがとうございます。
実数を使う場合は誤差が発生する場合があるということを
忘れないようにします。

お礼日時:2011/03/05 16:00

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