ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScriptの計算精度に関する豆知識(まとめ)

JavaScriptの計算精度に関する豆知識(まとめ)

青灯夜游
青灯夜游オリジナル
2018-09-17 15:07:042589ブラウズ

この章では、JavaScript の計算精度に関する小さな知識 (概要) を紹介し、2 進数と 10 進数の間の変換方法、JavaScript が数値を保存する方法、JavaScript が数値を読み取る方法を理解できるようにし、最後に例を示して説明します。 JavaScript は精度の問題による計算エラーを解決しますか?困っている友人は参考にしていただければ幸いです。

1. 前提知識のポイント

1. 10 進数を 2 進数に変換するにはどうすればよいですか?

整数部分を 2 で割って、商が 0 になるまでを求めます。小数部分を 2 倍して、積の小数部分が 0 になるまで順番に並べます。必要な精度が達成されています。

8转为二进制是多少?

8 / 2 = 4...0  取0
4 / 2 = 2...0  取0
2 / 2 = 1...0  取0
1 / 2 = 0...1  取1

二进制结果为:1000

0.25转为二进制是多少?

0.25 * 2 = 0.50  取0
0.50 * 2 = 1.00  取1

二进制结果为:01

于是可得出8.25的二进制表示:1000.01

2. 2 進数を 10 進数に変換するにはどうすればよいですか?

注: 2 進数から 10 進数への変換では、整数部分と小数部分は分離されません。

二进制1000.01转为十进制

1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0 + 0 * 2^-1 + 0 * 2^-2 = 8.25

2. JavaScript は数値をどのように保存しますか?

JavaScript の数値は、 IEEE 754 標準。

  • sign ビット (符号): 正と負の符号を表すために使用される 1 ビット (0 は正を意味し、1 は負を意味します)

  • exponent(指数): べき乗を表すために使用され、11 桁

  • #mantissa (仮数): 精度を表すために使用され、52 桁

JavaScriptの計算精度に関する豆知識(まとめ)

# 接点のない人にとっては、非常に漠然とした理解かもしれませんが、次に、そのプロセスを詳しく説明します。では、上記の 10 進数 8.25 が JS にどのように保存されるかを見てみましょう。

  • 10 進数 8.25 は 2 進数 1000.01 に変換されます。

  • 2 進数 1000.01 は、2 進数の科学表記法 1.00001 * 2^4; で表すことができます。

  • #00001 ※2^4の小数部00001(2進数)が仮数部(仮数)、4(10進数)+1023が指数(指数)になります(理由は後ほど説明します) 1023);
  • 次に、指数 4 を 1023 に加算し、バイナリ 10000000011 に変換する必要があります。
  • 10 進数の 8.25 は正の数値です。したがって、シンボルは 0 として実稼働中に 2 つあります。
  • ## 8.25 最終的なバイナリ保存 0-10000000011-00000000000000000000000000000000000000000 000 000 00000000000 数
  • ## 0 を追加します。桁数が足りない場合;

手順 2 で取得した科学表記法の整数部分 1 を忘れているようです。これは、精度を高めるために Javascript が使用されているためです。精度の場合、この 1 は省略されます。 この方法では、(バイナリ) 52 ビットの仮数のみを保存できますが、実際には 53 (バイナリ) ビットがあります。

  • 指数部は 11 ビットで、範囲は表現されます。は [0 , 2047] です。科学的表記法の指数は正または負の場合があるため、中間の数値は 1023 です。[0,1022] は負として表現され、[1024,2047] は正として表現されます。 これは、科学表記法の指数が 1023 を加えて保存される理由も説明します。

  • 3. JavaScript は数値をどのように読み取るのか
  • #8.25 0-10000000011-00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

#まず、指数部の 2 進数 1000000001 を取得し、それを 10 進数の 1027 に変換します。1027 から 1023 を引いたものが実際の指数 4 です。

仮数部 0000100000000000000000000000000000000000000000000 を取得します。実際の値は 0.00001 (次の 0 は書き込まれません) で、無視した 1 を追加して 1.00001 を取得します。最初の桁は 0 なので、この数値は正の数であるため、2 進数の科学表記法は 1.00001 * 2^4 となり、10 進数に変換すると、

  1. # となります。

    ##IV. JavaScript の精度の問題を 0.1 0.2 から見てみる

  2. ここで本題に入ります。前の原理の説明を理解すると、この部分は簡単になります。理解する。 。

  3. 0.1 0.2 を計算するには、まずこれら 2 つの浮動小数点数を読み取る必要があります。
  4. 0.1 は 64 ビットの 2 進浮動小数点数として保存されます。上記の手順は?

まず、0.1 をバイナリに変換します。整数部分は 0、小数部分は次のようになります: 0001100110011001100110011001100110011... おい、ここに無限ループがある。どうすればよいかする?今は無視してください。#得られる無限ループの 2 進数は、科学表記法で 1.100110011001100110011001100110011... * 2^-4;

# と表現されます。 # #指数ビットは -4 1023 = 1019、変換ビットは 11 桁の 2 進数 01111111011;

仮数ビットは無限ループですが、倍精度です。浮動小数点数は仮数部 52 ビットを規定しているため、52 ビットを超える部分は省略され、10011001100110011001100110011001100110011001100110 10

は最終的に 0.1 の 64 ビット 2 進浮動小数点数になります。 100110011001100110 0110011001100110011001100110011010

    同上,0.2存储为64位二进制浮点数:0-01111111100-1001100110011001100110011001100110011001100110011010

    读取到两个浮点数的64为二进制后,再将其转化为可计算的二进制数

    1. 0.1转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1019 - 1023)——0.00011001100110011001100110011001100110011001100110011010;

    2. 0.2转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1020 - 1023)——0.0011001100110011001100110011001100110011001100110011010;

    接着将两个浮点数的二进制数进行加法运算,得出0.0100110011001100110011001100110011001100110011001100111转化为十进制数即为0.30000000000000004

    不难看出,精度缺失是在存储这一步就丢失了,后面的计算只是在不精准的值上进行的运算。

    五. javascript如何解决精度问题出现的计算错误问题

    对于小数或者整数的简单运算可如下解决:

    function numAdd(num1, num2) { 
      let baseNum, baseNum1, baseNum2; 
      try { 
        baseNum1 = String(num1).split(".")[1].length; 
      } catch (e) { 
        baseNum1 = 0; 
      } 
      try { 
        baseNum2 = String(num2).split(".")[1].length; 
      } catch (e) { 
        baseNum2 = 0;
      } 
      baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
      return (num1 * baseNum + num2 * baseNum) / baseNum;
    };

    如:0.1 + 0.2 通过函数处理后,相当于 (0.1 * 10 + 0.2 * 10) / 10

    但是如同我们前面所了解的,浮点数在存储的时候就已经丢失精度了,所以浮点数乘以一个基数仍然会存在精度缺失问题,比如2500.01 * 100 = 250001.00000000003, 所以我们可以在以上函数的结果之上使用toFixed(),保留需要的小数位数。

    一些复杂的计算,可以引入一些库进行解决


    以上がJavaScriptの計算精度に関する豆知識(まとめ)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。