- ベストアンサー
C言語のfloat型変数の値代入と表示について
- C言語におけるfloat型変数の値の代入と表示について質問があります。実行結果が期待と異なる理由について教えてください。
- float型変数の値の代入と表示に関して、C言語のコードを実行してみた結果、意図した値と実際の値に微妙な差異があることに気づきました。この差異の原因について説明してください。
- C言語においてfloat型変数の値を代入し表示すると、予期しない数値が表示される現象に遭遇しました。この現象の理由について詳しく教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
IBMのページから http://www-06.ibm.com/jp/domino04/lotus/support/faqs/faqs.nsf/all/729933 基本的に小数点以下の数値を含むものは(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.html
その他の回答 (3)
- kmee
- ベストアンサー率55% (1857/3366)
あとは、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を使うようにしましょう。
お礼
回答いただき、ありがとうございます。 double型で試したところ、 50.1は「50.100000」、50.456は「50.456000」と結果表示されることを確認しました。 floatとdoubleで有効桁が異なるため丸め込みの桁数が変わり、 結果も異なることが理解できました。 ありがとうございます。
- tsukasa-12r
- ベストアンサー率65% (358/549)
簡単に言うと誤差です。 float flVal = 50.1; とすると、float 型の値として 50.1 に最も近い 50.456001 が代入されたのだと思います。 ↓を読むと納得できると思います。 http://pc.nikkeibp.co.jp/pc21/special/gosa/eg4.shtml あと、参考までに http://ja.wikipedia.org/wiki/%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0
お礼
回答いただき、ありがとございます。 紹介していただいた日経のページに、 丁寧に解説が載っていましたのでじっくり読ませていただき、理解できました。 ありがとうございました。
- k_kota
- ベストアンサー率19% (434/2186)
特殊なものを除くと、floatは二進数です。 なので、10進数ではきれいに表せる数字であってもきれいに表現できない場合があります。 少なくとも有限の桁数なら誤差が発生します。 それが困る場合は内部的に10進数の計算を使えるするものもありますが、一般的ではありません。 とりあえず、コンピュータで実数を使う場合はそのようなことが発生するというのは覚えておく必要があります。
お礼
回答をいただき、ありがとうございます。 実数を使う場合は誤差が発生する場合があるということを 忘れないようにします。
お礼
詳しい解説ありがとうございます。 float型が内部的に2進数でどのように保存されているか、 2進数から10進数にどのように変換される過程で誤差が発生するのか、勉強したいと思います。 また、データ型として固定小数点型という考え方があること、 C言語以外では固定小数点型をどのように扱うかの情報まで教えていただき、 ありがとうございました。参考にさせていただきます。