[解決済み] 通貨を表すのにDoubleやFloatを使ってはいけないのですか?
質問
いつも言われていることですが
決して
でお金を表現すること。
double
または
float
今回は、「なぜ?
きっとそれなりの理由があるのでしょうが、それが何なのかわからないだけです。
どうすれば解決するの?
なぜなら、浮動小数点数と倍数は、私たちがお金に使う10の基数を正確に表すことができないからです。この問題は、Javaだけでなく、基数2の浮動小数点型を使用するすべてのプログラミング言語に当てはまります。
10進法では、10.25は1025 * 10と書くことができます。 -2 (整数×10の累乗)です。 IEEE754浮動小数点数 は違いますが、非常にシンプルに考えるなら、代わりに2の累乗をかけるとよいでしょう。たとえば、164 * 2のような場合です。 -4 (整数×2の累乗)、これも10.25に相当します。これは、メモリ上で数字がどのように表現されているかということではなく、数学的な意味は同じです。
10進法であっても、この表記法ではほとんどの単純な分数を正確に表すことはできません。例えば、1/3は表現できない。10進数表現は繰り返し(0.3333...)なので、10の累乗を掛けて1/3となる有限の整数が存在しないのである。長い3の列と小さな指数で、333333333 * 10のように解決することができます。 -10 しかし、3倍しても1にはならない。
しかし、お金を数えるという目的では、少なくとも米ドルの価値が一桁以内の国の場合、通常は10の倍数を保存できればいいのです。 -2 だから、1/3が表現できなくても問題ない。
フロートとダブルの問題点は 大多数 実際、0と1の間の0.01の倍数(これは整数セントなので、お金を扱うときに重要です)で、IEEE754の2進浮動小数点数として正確に表現できるのは、0、0.25、0.5、0.75、1だけです。0.333333の例で言えば、0.01の浮動小数点値を10倍しても、0.1にはなりません。0.099999999786...といった具合になる。
お金を表現するのは
double
または
float
しかし、不正確な数値に対して足し算、引き算、掛け算、割り算を繰り返すうちに、誤差が増幅され、目に見えて不正確な数値が出来上がってしまうのです。このため、10の底の倍数に対して完璧な精度が要求される貨幣を扱うには、floatやdoublesは不適当なのです。
どの言語でも通用する解決策は、代わりに整数を使い、セントを数えることです。例えば、1025は10.25ドルです。いくつかの言語では、お金を扱うための組み込みの型も用意されています。特に、Javaには
BigDecimal
クラスがあり、C#は
decimal
という型があります。
関連
-
[解決済み】Lisp: なぜ (- 1e16 1) は 999999999999 ではなく 1000000000000 になるのでしょうか?
-
[解決済み] コアOCamlにおける浮動小数点数の絶対値
-
[解決済み] .NETでのdecimal, float, doubleの違い?
-
[解決済み] 通貨を表すのにDoubleやFloatを使ってはいけないのですか?
-
[解決済み] floatとdoubleの違いは何ですか?
-
[解決済み】IEEE754のNaN値に対して、すべての比較がfalseを返す根拠は何ですか?
-
[解決済み】ActiveRecordのFloatとDecimalの比較
-
[解決済み] 単精度浮動小数点演算と倍精度浮動小数点演算はどう違うのですか?
-
[解決済み] なぜNaNはNaNと等しくないのですか?[重複あり]
-
[解決済み] 2つの不等な浮動小数点数の引き算で0を得ることは可能ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン