>  기사  >  웹 프론트엔드  >  자바스크립트의 계산 정확도에 대한 약간의 지식(요약)

자바스크립트의 계산 정확도에 대한 약간의 지식(요약)

青灯夜游
青灯夜游원래의
2018-09-17 15:07:042526검색

이 장에서는 JavaScript의 계산 정확도에 대한 몇 가지 소소한 지식(요약)을 소개하여 이진수가 소수점 사이에서 어떻게 변환되는지, JavaScript가 숫자를 저장하는 방법, JavaScript가 숫자를 읽는 방법을 이해하고 마지막으로 JavaScript가 예제와 함께 작동하는 방법을 설명합니다. 정확성 문제로 인해 발생하는 계산 오류 문제를 해결합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

1. 전제 지식 포인트

1. 십진수를 이진수로 변환하는 방법은 무엇입니까?

정수 부분을 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. 이진수를 십진수로 변환하는 방법은 무엇인가요?

참고: 이진수를 십진수로 변환해도 정수 부분과 소수 부분이 분리되지 않습니다.

二进制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 표준

  • 을 채택한 64비트 배정밀도 부동 소수점 숫자입니다. 양수 및 음수 부호, 1비트(0은 양수, 1은 음수)

  • 지수(지수): 거듭제곱을 나타내는 데 사용, 11자리

  • mantissa(가수): 정확도를 나타내는 데 사용, 52자리

자바스크립트의 계산 정확도에 대한 약간의 지식(요약)

위의 내용은 이해하기 매우 모호할 수 있습니다. 다음으로 사례를 사용하여 프로세스를 자세히 설명하겠습니다. 위에서 언급한 십진수 8.25가 JS에 어떻게 저장되는지 살펴보세요.

  • 십진수 8.25는 이진수 1000.01로 변환됩니다.

  • 이진수 1000.01은 이진수 과학 표기법 1.00001 * 2^4

  • 00001 * 2^4 소수 부분 0000으로 표시됩니다. 1(바이너리) 가수(mantissa), 4(십진수) 더하기 1023은 지수(지수)입니다(1023이 추가되는 이유는 나중에 설명하겠습니다).

  • 다음으로 지수 4를 1023에 추가하고 이진수 10000000011로 변환해야 합니다.

  • 십진수 8.25는 양수이므로 이진수 기호는 0

  • 8.25 최종 이진수 저장은 0-10000000011-00001000000000000000000000000000000000000000입니다. 000000

참고:

  • 이 충분하지 않은 경우 0 Supplement를 사용합니다.

  • 2단계에서 얻은 과학적 표기법에서 정수 부분 1을 잊어버린 것 같습니다. 이는 Javascript가 정확성을 최대화하기 위해 이 1을 생략하기 때문입니다. 이런 식으로 (이진) 52비트 가수만 저장할 수 있지만 실제로는 53(이진) 비트가 있습니다. 지수 부분은 11비트이고 표시되는 범위는 과학적 표기법으로 인해 [0, 2047]입니다. 의 지수는 양수 또는 음수일 수 있으므로 중간 숫자는 1023입니다. [0,1022]는 음수를 나타내고, [1024,2047]은 양수를 나타냅니다. 이는 또한 과학 표기법의 지수에 1023을 추가하여 저장되는 이유를 설명합니다.

  • 3. 자바스크립트는 어떻게 숫자를 읽나요

우리는 여전히 8.25 0-10000000011-00001000000000000000000000000000000000000000 000의 바이너리를 사용합니다. 0000 to talk

먼저 지수 부분의 이진수 1000000001을 구해 다음과 같이 변환합니다. 십진수 1027, 1027 빼기 1023은 실제 인덱스 4입니다. 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000 01;

  1. 첫 번째 비트가 0이므로 우리 숫자는 양수이고 이진 과학 표기법은 1.00001 * 2입니다. ^4. 그런 다음 이를 십진수로 변환하면

  2. 4. 0.1 +0.2부터 자바스크립트 정밀도 문제를 살펴보겠습니다.
  3. 여기서 주요 주제를 살펴보겠습니다. .앞의 원리 설명을 이해하고 나면 이 부분도 이해하기 쉬워질 것입니다.

0.1+0.2를 계산하려면 먼저 이 두 부동 소수점 숫자를 읽어야 합니다. 0.1은 64비트 이진 부동 소수점 숫자로 저장됩니다. 위 단계를 잊으셨나요? 이진 정수 부분은 0이고 소수 부분은 다음과 같습니다. 00011001100110011001100110011... 여기 무한 루프가 있습니다. 어떻게 해야 할까요? 지금은 그것을 무시하십시오. 비트는 11비트입니다. 이진수 01111111011;

가수 비트는 무한 루프이지만 배정밀도 부동 소수점 수는 52개의 가수 비트를 규정하므로 52비트를 초과하는 것은 생략되며, 100110011001100110011001100110011001100 1100110011010이 유지됩니다.

마지막으로 우리는 0.1 부동 소수점 수의 64비트 바이너리를 얻습니다: 0-01111111011-1001100110011001100110011001100110011001100110011010

同上,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(),保留需要的小数位数。

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


위 내용은 자바스크립트의 계산 정확도에 대한 약간의 지식(요약)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.