1. ホーム
  2. floating-point

[解決済み] 通貨を表すのにDoubleやFloatを使ってはいけないのですか?

2022-03-18 16:11:48

質問

いつも言われていることですが 決して でお金を表現すること。 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 という型があります。