js 부동 소수점 숫자 정밀도 문제를 해결하는 방법

一个新手
풀어 주다: 2017-09-25 10:34:06
원래의
1596명이 탐색했습니다.

대부분의 언어는 부동 소수점 숫자를 다룰 때 정밀도 문제에 직면하지만 JS에서는 특히 심각한 것 같습니다. 예를 살펴보겠습니다

alert(45.6*13)
결과는 실제로 592.800000000001입니다. 물론 추가 등도 가능합니다. 이런 문제가 있을 겁니다
JS 오류인가요?
물론 그렇지 않습니다. 컴퓨터가 올바른 이진 부동 소수점 연산을 수행하고 있지만 문제는 십진수를 입력하고 컴퓨터가 이진수로 연산을 수행할 때 두 가지가 항상 잘 변환되지 않고 때로는 올바른 결과를 얻는다는 것입니다. , 하지만 때로는 운이 좋지 않을 때도 있습니다
alert(0.7+0.1);//Output 0.7999999999999999
alert(0.6+0.2);//Output 0.8

십진수 두 개를 입력하고 이진수로 변환한 다음 변환합니다. 돌아와서, 변환 과정에서 자연스럽게 손실이 발생합니다
그러나 일반적인 손실은 곱셈과 나눗셈 연산에서 더 많은 경우가 많으며 JS도 간단한 덧셈과 뺄셈에서 이런 문제가 발생합니다. 보시다시피 이 오류도 매우 작습니다. 네, 그런데 나오지 않아야 하는데
그렇다면 어떻게 해결해야 할까요? ECMA4에 해결책이 있는 것 같은데 지금은 그다지 실용적이지 않습니다
0.7+0.1 같은 방법 중 하나를 먼저 0.1과 0.7에 10을 곱한 뒤 더해줍니다. , 10으로 나누기
또한 이 문제를 해결하기 위해 몇 가지 함수를 작성할 수 있습니다. Baidu와 Google에는 많지만 복잡한 부동 소수점 연산을 수행하는 데 JS를 사용하지 않는 것이 가장 좋습니다. 이것에 유용합니다

<script type="text/javascript">  

    // 两个浮点数求和  
    function accAdd(num1,num2){  
       var r1,r2,m;  
       try{  
           r1 = num1.toString().split(&#39;.&#39;)[1].length;  
       }catch(e){  
           r1 = 0;  
       }  
       try{  
           r2=num2.toString().split(".")[1].length;  
       }catch(e){  
           r2=0;  
       }  
       m=Math.pow(10,Math.max(r1,r2));  
       // return (num1*m+num2*m)/m;  
       return Math.round(num1*m+num2*m)/m;  
    }  

    // 两个浮点数相减  
    function accSub(num1,num2){  
       var r1,r2,m;  
       try{  
           r1 = num1.toString().split(&#39;.&#39;)[1].length;  
       }catch(e){  
           r1 = 0;  
       }  
       try{  
           r2=num2.toString().split(".")[1].length;  
       }catch(e){  
           r2=0;  
       }  
       m=Math.pow(10,Math.max(r1,r2));  
       n=(r1>=r2)?r1:r2;  
       return (Math.round(num1*m-num2*m)/m).toFixed(n);  
    }  
    // 两数相除  
    function accp(num1,num2){  
       var t1,t2,r1,r2;  
       try{  
           t1 = num1.toString().split(&#39;.&#39;)[1].length;  
       }catch(e){  
           t1 = 0;  
       }  
       try{  
           t2=num2.toString().split(".")[1].length;  
       }catch(e){  
           t2=0;  
       }  
       r1=Number(num1.toString().replace(".",""));  
       r2=Number(num2.toString().replace(".",""));  
       return (r1/r2)*Math.pow(10,t2-t1);  
    }  

    function accMul(num1,num2){  
       var m=0,s1=num1.toString(),s2=num2.toString();   
    try{m+=s1.split(".")[1].length}catch(e){};  
    try{m+=s2.split(".")[1].length}catch(e){};  
    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);  
    }  

  </script>  

    <script>  
    document.write("使用js原生态方法");  
    document.write("<br/> 1.01 + 1.02 ="+(1.01 + 1.02));  
    document.write("<br/> 1.01 - 1.02 ="+(1.01 - 1.02));  
    document.write("<br/> 0.000001 / 0.0001 ="+(0.000001 / 0.0001));  
    document.write("<br/> 0.012345 * 0.000001 ="+(0.012345 * 0.000001));  
    document.write("<br/><hr/>");  
    document.write("<br/>使用自定义方法");  
    document.write("<br/> 1.01 + 1.02 ="+accAdd(1.01,1.02));  
    document.write("<br/> 1.01 - 1.02 ="+accSub(1.01,1.02));  
    document.write("<br/> 0.000001 / 0.0001 ="+accp(0.000001,0.0001));  
    document.write("<br/> 0.012345 * 0.000001 ="+accMul(0.012345,0.000001));  
    </script>
로그인 후 복사

위 내용은 js 부동 소수점 숫자 정밀도 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!