- ベストアンサー
C++でおつり計算プログラムを作成する方法
- C++を使用しておつり計算プログラムを作成する方法について教えてください。
- プログラム内でdoubleとintの変換が原因でおつりが1セント少なくなってしまう問題が発生しています。
- 正しく動作するようにするための解決策を教えていただきたいです。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
double型を使っていることがそもそもの間違いです。 汎整数型を使って、内部的にはすべてセントで表現するようにしましょう。
その他の回答 (6)
- Hayashi_Trek
- ベストアンサー率44% (366/818)
この問題に限っていえば、 計算中のお金の単位をドルからセントにかえて整数計算し 最後に表示するときにドルとセントに換算すれば誤差は出なくなります。
- jacta
- ベストアンサー率26% (845/3158)
そういえば、Macでは使えたかどうか忘れましたが、GCCは_Decimal64とか_Decimal128といった10進浮動小数点型をサポートしていますね。 C++ではなく、Cでなければ使えなかったと思いますが...
- Tacosan
- ベストアンサー率23% (3656/15482)
厳密に言えば「浮動小数点を使う」のがご法度ではなく「10進でない表し方を使う」のがご法度では>#4. 浮動小数であっても 10進であればさほど問題ないはず. TR 24733 が現在進行中ですね.
- MAXIMAX
- ベストアンサー率60% (50/83)
C++ に限りませんが、金額などを扱う場合、浮動小数点を使うことはご法度です。しかし、C++ では固定小数点はサポートされていませんので、工夫する必要が出てきます。 詳しい人なら自分で固定小数点クラスを作るのもいいですが、昔から使われているのは、long などで、内部的には 1000 倍(1000 の必要はありませんが)にして持たせる、などです。ただし、扱う金額を 1000 倍しても long の範囲で収まることが条件です。内部では 1000 倍した値で各種計算を行い、最終的に元の桁に戻します。延々と除算を繰り返すようなことをやると丸めが積み重なっていきますが、倍数を大きくすればするほど、その丸め誤差は小さくなってはいきます。
- chie65536(@chie65535)
- ベストアンサー率44% (8742/19841)
因みに、2進数化すると 0.1=0.000110011001100110011001100110011001100110011001100110011001100110... 0.01=0.000000101000111101011100001010001111010111000010100011110101110000... と言う循環少数になります。 循環部分を [] で表すと 0.1=0.0[0011]... 0.01=0.00[00001010001111010111]... となります。 コンピュータのメモリは有限ですから、無限に続く循環少数を正確に表す事は出来ません。
- chie65536(@chie65535)
- ベストアンサー率44% (8742/19841)
0.1、0.01は、double、float等に2進数化すると「循環少数」になる為、必ず誤差が出ます。 なので、0.1、0.01を扱う場合は、BCD(二進化十進数)を用いるか、固定小数点を用いねばなりません。 これは、C++に限った話ではありません。どんな言語でも同じです。 「セントを1として、すべて整数型で扱う」のも「固定小数点」と同義です。
お礼
皆さん、 回答をありがとうございました。もともと最初から間違っていたのですね。汎整数型を使ってみます。