非常简单的一个数学计算,但计算结果却令我惊讶!!alert(10.73*10);  // 正确结果应该是 107.3 ,但我得到的结果却是 107.30000000000001
alert(32.73*100); // 正确结果应该是 3273  ,但我得到的结果却是 3272.9999999999995就上面两个简单的数学计算,请大家测试一下上面那个简单的计算输出,看看结果是不是我说的那样,到底为什么会这样??如果我换成 alert(10.73*100); 则可以得到正确的结果 1073 ,但为什么乘以10就不正确了?还有,我发现 用 32.73 ,33.73 ,34.73 ,35.73 ,36.73 ,37.73 ,38.73 ,39.73 ,40.73 ,41.73 分别乘以 100 就会出现结果不正确的问题,但用 33.73 ,34.73 ,35.73 ,36.73 ,37.73 ,38.73 ,39.73 ,40.73 ,41.73 分别乘以 1000 就能正确显示结果,但乘以 10 或者乘以 100 就会出问题,另外我用 32.73 乘以 1000 或者 10000 等等,反正只要是 10 的倍数,结果都会出现问题,到底是什么原因??本人分别用 winxp 下的 IE7.0 和 win2003 下的 IE8.0 做过测试,均出现上面我所说的情况,请各位牛人进来解答一下!

解决方案 »

  1.   


    //除法函数,用来得到精确的除法结果
    //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
    //调用:accDiv(arg1,arg2)
    //返回值:arg1除以arg2的精确结果
    function accDiv(arg1,arg2){
         var t1=0,t2=0,r1,r2;
         try{t1=arg1.toString().split(".")[1].length}catch(e){}
         try{t2=arg2.toString().split(".")[1].length}catch(e){}
         with(Math){
             r1=Number(arg1.toString().replace(".",""))
             r2=Number(arg2.toString().replace(".",""))
             return (r1/r2)*pow(10,t2-t1);
         }
    }//给Number类型增加一个div方法,调用起来更加方便。
    Number.prototype.div = function (arg){
         return accDiv(this, arg);
    }//乘法函数,用来得到精确的乘法结果
    //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
    //调用:accMul(arg1,arg2)
    //返回值:arg1乘以arg2的精确结果
    function accMul(arg1,arg2)
    {
         var m=0,s1=arg1.toString(),s2=arg2.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)
    }//给Number类型增加一个mul方法,调用起来更加方便。
    Number.prototype.mul = function (arg){
         return accMul(arg, this);
    }//加法函数,用来得到精确的加法结果
    //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
    //调用:accAdd(arg1,arg2)
    //返回值:arg1加上arg2的精确结果
    function accAdd(arg1,arg2){
         var r1,r2,m;
         try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
         try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
         m=Math.pow(10,Math.max(r1,r2))
         return (arg1*m+arg2*m)/m
    }//给Number类型增加一个add方法,调用起来更加方便。
    Number.prototype.add = function (arg){
         return accAdd(arg,this);
    }
      

  2.   

    这个应该跟cpu的浮点算法有关,比如,1,有的CPU就解释成0.999999999999去,这样,显然会出现你说的这种情况。
    js浮点数计算时,直接截取位数就好
      

  3.   

    回复 xzy88 :
    如果是CPU的关系,那应该使用什么程序语言来计算都会出现这种错误的了,但我用 asp 来输出这个计算结果没有出现问题啊
    <%
    response.write(32.73*100)   --能得到正确结果 3273,不会出现js那个问题
    %>
      

  4.   

    那我现在到底应该怎么做呢??我现在做的是一个电子商务网站,里面有些产品的价格是32.73元一件,现在客户要买100件,我就只能用 32.73*100 来计算总价的了,但现在用javascript来计算出现了错误,不是我想要的3273 结果,现在到底我要怎么来计算价格啊??难道你们做电子商务网站还要另外写一套加减乘除的代码吗??不是直接用javascript里面的 + - * / 来运算吗??我现在非常纳闷啊!!
      

  5.   

    因为js里带小数点的都认为是float类型,js里没有类似于deicimal类型,而float类型是单精度浮点型,既然是有精度的,那么就有可能计算后的结果会出人意料。
      

  6.   


    很多人都在说原理,关键是怎么解决这个问题,
    纠正错误的js代码在3楼早就发给你了。引用这个JS
    var money=32.73*100 
    改成
    var money = accMul(32.73,100)哎。。
      

  7.   

    String.prototype.toFloat=Number.prototype.toFloat=function(len,isRound){
        len=typeof len=='number'?len:1,isRound=typeof isRound=='boolean'?isRound:!0;
        try{
            var c=len?(isRound?(this*1).toFixed(len)*1:this.toString().replace(new RegExp("([0-9]+\.[0-9]{"+len+"})[0-9]*","g"),"$1")*1):(this*1);
            return isNaN(c)?this:c;
        }catch(e){
            return this*1;//防止小数位数字越界
        }
    }
    /// <summary>
    /// String,Number原型扩展:保留指定的小数位数[可选择是否使用四舍五入]
    /// </summary>
    /// <param name="len">需要保留的小数位,默认为1</param>
    /// <param name="isRound">是否是舍五入[可选项:默认true]</param>
    /// <returns>数据类型:Number(浮点数)</returns>
    四舍五入:    (2.35555).toFloat(3)=2.356
    非四舍五入:  (2.35555).toFloat(3,!1)=2.355
    简单容错:    (2.35555).toFloat(!0)=2.4四舍五入:    "2.35555".toFloat(3)=2.356
    非四舍五入:  "2.35555".toFloat(3,!1)=2.355
    简单容错:    "aaaaa".toFloat(!0)='aaaaa'
    ================================================
    //四舍五入
    alert((10.73*10).toFloat(2));//107.3 
    alert((32.73*100).toFloat(2));//3273 
    //如果不需要四舍五入
    alert((10.73*10).toFloat(14,!1));//107.30000000000001
    alert((10.73*10).toFloat(2,!1));//107.3
     
    alert((32.73*100).toFloat(2,!1));//3272.99