>  기사  >  웹 프론트엔드  >  js의 숫자가 너무 많아 매개변수 정밀도가 손실되는 예를 공유하세요.

js의 숫자가 너무 많아 매개변수 정밀도가 손실되는 예를 공유하세요.

零下一度
零下一度원래의
2017-04-27 14:49:193279검색

js의 자릿수가 너무 커서 매개변수 정밀도가 손실되는 예를 공유해 주세요

최근에 매개변수를 전달할 때 이상한 문제가 발생했습니다. js 함수에 비트가 전달되는 경우 숫자가 상대적으로 큽니다. 인수를 인쇄해 보면 전달된 매개변수가 변경된 것을 확인할 수 있습니다.

그러다가 확인해보니 정말 js 정확도가 떨어져서 발생한 현상이었습니다. 내 해결책은 숫자 유형을 문자 유형 전송으로 변경하여 정확도가 손실되지 않도록 하는 것입니다. 아래와 같습니다.

JS 숫자가 정밀도를 잃는 이유

컴퓨터의 바이너리 구현과 자릿수 제한 . 일부 숫자는 유한하게 표현될 수 없습니다. 파이 3.1415926..., 1.3333... 등과 같은 일부 무리수를 유한하게 표현할 수 없는 것과 같습니다. JS는 IEEE를 준수합니다. 754 사양은 배정밀도 저장소(이중 정밀도)를 사용하며 64비트를 차지합니다. 그림과 같이

의미

  • 1비트를 사용하여 부호비트를 표현합니다.

  • 11비트는 지수를 나타내는 데 사용됩니다.

  • 52비트는 가수를 나타냅니다.

과 같은 부동 소수점 숫자
0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
0.2 >> 0.0011 0011 0011 0011…(0011无限循环)

이때는 십진수만 흉내낼 수 있습니다. 반올림을 하는데 이진수는 0과 1 두 개뿐이므로 0이 되어 1로 반올림됩니다. 이는 컴퓨터의 일부 부동 소수점 연산에서 오류 및 정밀도 손실의 근본 원인입니다.

큰 정수의 정밀도 손실은 부동소수점 숫자의 정밀도 손실과 본질적으로 동일합니다. 최대 가수 자릿수는 52이므로 JS에서 정확하게 표현할 수 있는 가장 큰 정수는 Math.pow(2, 53) 십진수로는 9007199254740992이다.

9007199254740992보다 크면 정확도가 떨어질 수 있음

9007199254740992     >> 10000000000000...000 // 共计 53 个 0
9007199254740992 + 1 >> 10000000000000...001 // 中间 52 个 0
9007199254740992 + 2 >> 10000000000000...010 // 中间 51 个 0

실제로

9007199254740992 + 1 // 丢失
9007199254740992 + 2 // 未丢失
9007199254740992 + 3 // 丢失
9007199254740992 + 4 // 未丢失

결과는 그림과 같습니다

위의 내용은 괜찮습니다. 컴퓨터의 이진수 표현에서는 유한해 보이는 숫자가 실제로 무한하다는 것을 알고 있습니다. 저장 자릿수 제한으로 인해 "반올림"이 발생하고 정밀도가 손실됩니다.

想了解更深入的分析可以看这篇论文(又长又臭):What Every Computer Scientist Should Know About Floating-Point Arithmetic

三、解决方案

对于整数,前端出现问题的几率可能比较低,毕竟很少有业务需要需要用到超大整数,只要运算结果不超过 Math.pow(2, 53) 就不会丢失精度。

对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。解决方式:把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数

// 0.1 + 0.2
(0.1*10 + 0.2*10) / 10 == 0.3 // true

위 내용은 js의 숫자가 너무 많아 매개변수 정밀도가 손실되는 예를 공유하세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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