JavaScript を超えて - プログラミングにおいて + が等しくない理由

DDD
リリース: 2024-09-13 22:17:02
オリジナル
746 人が閲覧しました

JavaScript は、開発者がこの一見不可解な結果に初めて遭遇したときに、頻繁に嘲笑されます。

0.1 + 0.2 == 0.30000000000000004
ログイン後にコピー

JavaScript による数値の処理に関するミームは広く広まっており、多くの人がこの動作はこの言語に特有のものであると信じています。

Beyond JavaScript - Why  +  doesn

ただし、この問題は JavaScript に限定されるものではありません。これは、ほとんどのプログラミング言語が浮動小数点演算を処理する方法の結果です。

たとえば、同様の結果を生成するJavaGoのコード スニペットを次に示します。

Beyond JavaScript - Why  +  doesn

Beyond JavaScript - Why  +  doesn

コンピュータはネイティブに整数のみを保存できます。彼らは分数を理解していません。 (どうやってやるのでしょうか? コンピューターが算術演算を行う唯一の方法は、ライトをオンまたはオフにすることです。ライトはオンでもオフでも構いません。「半分」オンにすることはできません!) 浮動小数点数を表現する何らかの方法が必要です。 。この表現は完全に正確ではないため、多くの場合、0.1 + 0.2 は 0.3 と等しくなりません。

分母が記数系の基数の素因数で構成されるすべての分数は、他の分数には繰り返し小数が含まれますが、きれいに表現できます。たとえば、基数 10 の記数法では、1/2、1/4、1/5、1/10 などの分数は、それぞれの場合の分母が 2 または 5 (10 の素因数) で構成されているため、きれいに表現されます。ただし、1/3、1/6、1/7 などの分数には循環小数が含まれます。

同様に、二進法では、1/2、1/4、1/8 などの分数はきれいに表現されますが、他のすべての分数には反復小数が含まれます。これらの繰り返し小数の算術演算を実行すると、コンピューターの数値のバイナリ表現を人間が判読できる基数 10 の表現に変換するときに引き継がれる残りが生じます。これにより、ほぼ正しい結果が得られます。

この問題が JavaScript に限定されたものではないことがわかったので、この動作が発生する理由を理解するために、浮動小数点数が内部でどのように表現および処理されるかを調べてみましょう。

浮動小数点数が内部でどのように表され処理されるかを理解するには、まずIEEE 754浮動小数点標準を理解する必要があります。

IEEE 754 標準は、コンピューター システムで浮動小数点数を表現および演算するために広く使用されている仕様です。これは、さまざまなコンピューティング プラットフォームで浮動小数点演算を使用する際の一貫性を保証するために作成されました。ほとんどのプログラミング言語とハードウェア実装 (CPU、GPU など) はこの標準に準拠しています。

IEEE 754形式で数値を表す方法は次のとおりです。

Beyond JavaScript - Why  +  doesn

ここで、sは符号ビット (正の場合は 0、負の場合は 1)、Mは仮数部 (数値の桁を保持)、Eは、数値の位取りを決定する指数です。

この形式では、0.1、0.2、0.3 のような数値を正確に表すことができる M と E の整数値は見つかりません。最も近い結果を与える M と E の値のみを選択できます。

これは、10 進数のIEEE 754表記を決定するために使用できるツールです: https://www.h-schmidt.net/FloatConverter/IEEE754.html

IEEE 7540.25 の表記:

Beyond JavaScript - Why  +  doesn

IEEE 754それぞれ 0.1 と 0.2 の表記:

Beyond JavaScript - Why  +  doesn
Beyond JavaScript - Why  +  doesn

0.25 の場合の変換による誤差は 0 でしたが、0.1 と 0.2 にはゼロ以外の誤差があることに注意してください。

IEEE 754では、浮動小数点数を表現するための次の形式が定義されています。

  • 単精度 (32 ビット): 符号に 1 ビット、指数に 8 ビット、仮数に 23 ビット

  • 倍精度 (64 ビット): 符号に 1 ビット、指数に 11 ビット、仮数に 52 ビット

話を簡単にするために、32 ビットを使用する単精度形式を考えてみましょう。

0.1 の 32 ビット表現は次のとおりです。

0 01111011 10011001100110011001101
ログイン後にコピー

Here the first bit represents the sign (0 which means positive in this case), the next 8 bits (01111011) represent the exponent and the final 23 bits (10011001100110011001101) represent the mantissa.

This is not an exact representation. It represents ≈0.100000001490116119384765625

Similarly, the 32 bit representation of 0.2 is:

0 01111100 10011001100110011001101
ログイン後にコピー

This is not an exact representation either. It represents ≈0.20000000298023223876953125

When added, this results in:

0 01111101 11001101010011001100110
ログイン後にコピー

which is ≈0.30000001192092896in decimal representation.

In conclusion, the seemingly perplexing result of 0.1 + 0.2 not yielding 0.3 is not an anomaly specific to JavaScript, but a consequence of the limitations of floating-point arithmetic across programming languages. The roots of this behaviour lie in the binary representation of numbers, which inherently leads to precision errors when handling certain fractions.

以上がJavaScript を超えて - プログラミングにおいて + が等しくない理由の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!