ホームページ  >  記事  >  バックエンド開発  >  浮動小数点演算でエラーが発生する理由についての簡単な説明

浮動小数点演算でエラーが発生する理由についての簡単な説明

青灯夜游
青灯夜游転載
2021-07-15 18:53:0210390ブラウズ

この記事では、Python を例として、浮動小数点演算でエラーが発生する理由について説明します。エラーが発生する可能性がある状況を紹介してください。そしてそれをどうやって解決するのか?お役に立てば幸いです。

浮動小数点演算でエラーが発生する理由についての簡単な説明

[関連する推奨事項: Python3 ビデオ チュートリアル ]

コードを作成するときは、いわゆる浮動小数点エラーに遭遇することがあります。浮動小数点エラーの穴に足を踏み入れていないのであれば、それは幸運すぎるとしか言えません。

以下の Python の図を例に挙げます。0.1 0.20.3 と等しくなく、8.7 / 10 も ## と等しくありません。 #0.87、でも 0.869999…、とても奇妙です

浮動小数点演算でエラーが発生する理由についての簡単な説明

しかし、これは決してひどいバグではなく、Python の問題でもありませんしかし、浮動小数点数は演算を実行する際に避けられない結果であるため、JavaScript や他の言語でも同様です。

浮動小数点演算でエラーが発生する理由についての簡単な説明

コンピュータはどのように整数を格納するのでしょうか。 ( 整数)

浮動小数点エラーが存在する理由を説明する前に、まずコンピューターが

整数 を表すために 0 と 1 をどのように使用するかについて説明しましょう。誰もがバイナリを知っておく必要があります。 101 は $2^2 2^0$ (つまり 5) を表し、1010 は $2^3 2^1$ (つまり 10) を表します。

浮動小数点演算でエラーが発生する理由についての簡単な説明

符号なし 32 ビット整数の場合、0 または 1 を配置できる位置が 32 個あることを意味するため、最小値は

0000 です。 ..0000 は 0 で、最大値 1111...1111 は $2^{31} 2^{30} ... 2^1 2^0$、つまり 4294967295## を表します。 # 順列と組み合わせの観点から見ると、各ビットは 0 または 1 になる可能性があるため、変数全体の値には $2^{32}$ の可能性があり、

正確に

0 から $2 を表現できます。 ^ {23} - 1$ の間の任意の値 (エラーなし)。

浮動小数点

0 から $2^{23} - 1$ までの整数はたくさんありますが、最終的には

Limited

だけです。 $2^{32}$ ほどありますが、浮動小数点数は異なります。次のように考えることができます。1 から 10 までの整数は 10 個しかありませんが、 A は無限にあります。 5.1、5.11、5.111 などの浮動小数点数のリストは無限にあります。 しかし、32 ビット空間には 23² 個の可能性しかないため、すべての浮動小数点数をこの 32 ビット空間に詰め込むために、多くの CPU メーカーがさまざまな浮動小数点数表現方法を発明してきました。 CPUごとにフォーマットが異なると面倒なので、最終的に浮動小数点演算の一般的な規格としてIEEEが発行したIEEE 754が使われ、現在のCPUもこの規格に基づいて設計されています。

IEEE 754

IEEE 754 では、単精度 (32 ビット)、倍精度 (64 ビット)、特殊値 (無限大、NaN) など、多くのものが定義されています。など。

標準化浮動小数点数 8.5 を IEEE 754 形式に変更する場合は、まず次のことを行う必要があります。正規化を行います。8.5 を 8 0.5、つまり $2^3 (\cfrac{1}{2})^1$ に分割し、それをバイナリで書き込んで

1000.1

にし、最後に $1.0001 として書き込みます。 \ に 2^3$ を掛けます。これは 10 進科学表記法によく似ています。

単精度浮動小数点数IEEE 754 では、32 ビット浮動小数点数は 3 つの部分に分割されます。符号)、指数、分数の合計は 32 ビット

浮動小数点演算でエラーが発生する理由についての簡単な説明

符号: 左端の 1 ビット 正負の符号を表し、正の数の場合、符号は 0、それ以外の場合は 1
  • 指数: 中央の 8 ビットは、
  • 指数を使用して正規化後の累乗を表します。 真の値 127
  • の形式、つまり、 3 プラス 127 は 130 仮数 (小数部) に等しい: 右端の 23 ビットは
  • 1.0001## で始まる小数部分です # つまり、
  • 00011. の後に削除されるため、8.5 を 32 ビット形式で表現すると、次のようになります:

浮動小数点演算でエラーが発生する理由についての簡単な説明

どのような状況でエラーが発生しますか?

8 と 0.5 は両方とも 2 の累乗であるため、上記の 8.5 の例は $2^3 (\cfrac{1}{2})^1$ と表現できます。したがって、精度の問題はまったくありません。

しかし、8.9 の場合、2 のべき乗を加算する方法がないため、$1.0001110011... \times 2^3$ と表現せざるを得なくなり、約 $0.0000003$ の誤差も発生します。興味があれば、IEEE-754 Floating Point Converter の Web サイトにアクセスして試してみることができます。

#倍精度浮動小数点数

#前述の単精度浮動小数点数は、わずか 32 ビットで表されます。 IEEE 754では、誤差を小さくするために浮動小数点数を64ビットで表現することも定められており、32ビットに比べて小数部が23ビットから52ビットと2倍以上拡張されているため、当然精度は向上します。たくさん。

浮動小数点演算でエラーが発生する理由についての簡単な説明

先ほどの 8.9 を例に挙げると、64 ビットで表現するとより正確になりますが、8.9 を 2 の累乗の合計として完全に記述することはできません。小数になります。下位 16 ビットには依然としてエラーが存在しますが、単精度エラー 0.0000003

浮動小数点演算でエラーが発生する理由についての簡単な説明

同様の状況も # のようになります。 Python の ##1.00.999...999 に等しく、123122.999...999 に等しくなります。それらは非常に小さいので、小数に入れることができないため、バイナリ形式からは、すべてのバイナリ ビットは同じになります。

浮動小数点演算でエラーが発生する理由についての簡単な説明

#解決策

浮動小数点数の誤差は避けられないため、許容しなければなりません。より一般的な処理方法:

最大許容誤差 ε (イプシロン) を設定します一部の言語では、いわゆるイプシロンが提供されます。浮動小数点誤差の許容範囲内かどうかを判断するために使用されます。Python では、epsilon の値は約 $2.2e^{-16}$

浮動小数点演算でエラーが発生する理由についての簡単な説明 #、つまり、演算中に浮動小数点エラーが原因で問題が発生するのを避けるために、

0.1 0.2 == 0.3

0.1 0.2 — 0.3 に書き換えることができます。 0.1 プラス 0.2 を比較します。それは 0.3 に等しいですか? <code>もちろん、システムがイプシロンを提供しない場合は、自分でイプシロンを定義して、約 2 の -15 乗に設定することもできます。

完全に使用します計算用の 10 進法 浮動小数点エラーが発生する理由は、10 進数を 2 進数に変換するプロセスで、小数部分を仮数部にすべて詰め込むことができないためです。変換時にエラーが発生した場合は、変換する必要はなく、10 進数を使用して計算を行うだけです。

Python には 10 進数というモジュールがあり、JavaScript にも同様のパッケージがあります。ペンと紙を使って 0.1 0.2 を間違いや間違いなく計算できるのと同じように、10 進数で計算を実行するのに役立ちます。

浮動小数点演算でエラーが発生する理由についての簡単な説明10 進数を使用して計算すると浮動小数点数のエラーを完全に回避できますが、Decimal の 10 進数計算がシミュレートされるため、最下位レベルの CPU 回路では 2 進数が使用されます。ネイティブの浮動小数点演算よりもはるかに遅いため、すべての浮動小数点演算に Decimal を使用することはお勧めできません。

プログラミング関連の知識について詳しくは、

プログラミング入門

をご覧ください。 !

以上が浮動小数点演算でエラーが発生する理由についての簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。