zoukankan      html  css  js  c++  java
  • 浮点数精度问题

    大多数语言在处理浮点数的时候都会遇到精度问题,但是在JS里似乎特别严重,来看一个例子

    alert(45.6*13);
    

    结果居然是592.800000000001,当然加法之类的也会有这个问题

    那这是js的错误吗?

    当然不是,你的电脑做着正确的二进制浮点运算,但问题是你输入的是十进制的数,电脑以二进制运算,这两者并不是总是转化那么好的,有时候会得到正确的结果,但有时候就不那么幸运了

    alert(0.7+0.1);//输出0.7999999999999999
    alert(0.6+0.2);//输出0.8
    
    

    你输入两个十进制数,转化为二进制运算过后再转化回来,在转化过程中自然会有损失了

    但一般的损失往往在乘除运算中比较多,而JS在简单的加减法里也会出现这类问题,你也看到了,这个误差也是非常小的,但是却是不该出现的

    那该怎么解决呢,ECMA4似乎给了解决方法,但是现在倒不是那么实用的

    一种方法,比如0.7+0.1,先把0.1和0.7都乘10,加完之后再除10

    另外可以自己写点函数来解决这个问题,自己百度谷歌一下应该有很多,但是最好还是不要用JS做一些复杂的浮点运算,毕竟JS更多的作用不在于此

    <script type="text/javascript">
    
        // 两个浮点数求和
        function accAdd(num1,num2){
           var r1,r2,m;
           try{
               r1 = num1.toString().split('.')[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('.')[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 accDiv(num1,num2){
           var t1,t2,r1,r2;
           try{
               t1 = num1.toString().split('.')[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 ="+accDiv(0.000001,0.0001));
        document.write("<br/> 0.012345 * 0.000001 ="+accMul(0.012345,0.000001));
      </script>
  • 相关阅读:
    【LeetCode】Validate Binary Search Tree ——合法二叉树
    协程(Coroutine)并不是真正的多线程(转)
    转: Android 软件开发之如何使用Eclipse Debug调试程序详解(七)
    转: eclipse 快捷键列表(功能清晰版本)
    电商初级技术方案探讨
    转: Vue.js——60分钟组件快速入门(上篇)
    音视频推荐书籍
    md5sum使用注意事项
    转: java DES的算法片码
    ant 命令学习详解
  • 原文地址:https://www.cnblogs.com/vscss/p/5650046.html
Copyright © 2011-2022 走看看