1. ホーム
  2. math

[解決済み】なぜ10進数は2進数で正確に表現できないのですか?

2022-03-30 10:11:50

質問

SOには、浮動小数点数の表現について、いくつかの質問が投稿されています。例えば、10進数の0.1は正確な2進数表現を持っていないので、==演算子を使って他の浮動小数点数と比較するのは危険です。浮動小数点数の表現原理は理解している。

数学的な観点から、なぜ小数点の右側にある数字は左側にある数字よりも特別なのでしょうか?

たとえば、61.0という数字は正確な2進法で表現されます。なぜなら、どんな数字も積分部分は常に正確だからです。しかし、6.10という数値は正確ではありません。10進数を1つ動かしただけなのに、突然ExactopiaからInexactvilleになってしまったのだ。数学的には、この2つの数字には本質的な違いはないはずです。

一方、小数点を1桁下げて「610」という数字を出しても、ここは「エキザクトピア」のままだ。その方向(6100、610000000、610000000000000)に進み続けても、正確、正確、正確なのです。しかし、小数点以下の数字がある閾値を超えると、数字はもはや正確ではなくなります。

どうなっているんだ?

編集:明確にするために、私はIEEEなどの業界標準の表現についての議論から離れ、私が信じる数学的に"純粋な"方法にこだわりたいのです。10進法では、位置の値は次のとおりです。

... 1000  100   10    1   1/10  1/100 ...

バイナリでは、こうなる。

... 8    4    2    1    1/2  1/4  1/8 ...

また、これらの数字には任意の制限が加えられていない。位置は左へ右へと無限に増えていく。

解き方は?

10進数 可能 は、十分なスペースがあれば、正確に表現することができます。 バイナリ の点数です。もし、浮動小数点数の 10進数 ポイント型(例. System.Decimal の場合、2進浮動小数点では正確に表現できない多くの値を正確に表現することができます。

例えば、皆さんが慣れ親しんでいる10の底では、1/3を正確に表現することはできません。0.3333333なのですが...。(繰り返し)です。0.1を2進数の浮動小数点数で表現できないのも、まったく同じ理由です。3、9、27は正確に表現できますが、1/3、1/9、1/27は表現できないのです。

問題は、3が10の倍数でない素数であることだ。それは、次のような場合には問題にはならない。 乗算 を3倍することで、常に整数を掛けることができ、問題が発生することはありません。しかし 割る を、素数で基数の因数でない数で割ると、トラブルに見舞われることがあります(そして ウィル 1をその数で割ろうとすると、そうなります)。

0.1 は通常、2 進浮動小数点では正確に表現できない正確な 10 進数の最も単純な例として使用されますが、間違いなく 0.2 は 1/5 であり、5 は 10 進数と 2 進数の間で問題を引き起こす素数なので、より単純な例と言えます。


有限表現の問題に対処するための副次的なメモ。

浮動小数点型の中には、以下のようにサイズが固定されているものがあります。 System.Decimal のようなものもあります。 java.math.BigDecimal しかし、システムメモリであれ、配列の理論的な最大サイズであれ、ある時点で限界に到達します。しかし、これはこの回答の主旨とは全く別のポイントです。たとえ、本当に任意の数のビットを使用できたとしても、10進数の0.1を浮動2進数表現で正確に表現することはできないのです。逆に、任意の数の10進数がある場合、以下のようになります。 できる 浮動2進数として正確に表現できる数であれば、どんな数でも正確に表現することができます。