toFixed()方法不仅仅截去多余的小数位,同时它还根据截取位置的下一个小数位进行四舍五入。例如,对于数值10.739,截取到小数点后的两位数,结果将是10.74。而对于数值10.732,截取到小数点后的两位数,结果将是10.73。
注意,在JavaScript中我们只能截取小数点之后0位~20位的小数。
toFixed()方法仅被高版本的浏览器所支持,所以在使用之前最好先检查一下浏览器是否支持该方法,检查的代码如下所示:
var varNumber = 22.234
if (varNumber.toFixed)
{
varNumber = varNumber.toFixed(2)
}
else //浏览器不支持toFixed()就使用其他方法
{
var div = Math.pow(10,2)
varNumber = Math.round(varNumber * div) / div
}
这样可以解决,但你想问,怎么可能多出这么小数点出来。
为什么会出现如此无法理解的答案?
我Google了一下,发现原来这是JavaScript浮点运算的一个bug。
比如:7*0.8 JavaScript算出来就是:5.6000000000000005
网上找到了一些解决办法,就是重新写了一些浮点运算的函数。
下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:
程序代码
//除法函数,用来得到精确的除法结果
//说明: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)
}
在你要用的地方包含这些函数,然后调用它来计算就可以了。
比如你要计算:7*0.8 ,则改成 (7).mul(8)
其它运算类似,就可以得到比较精确的结果。
--------------------------------------------------------------------------
以上是在网上一个JS牛人的博客上转载的,不过上面只提及了加法、乘法和除法的解决办法。
这个时候可能很多人就会想,有了加法,减法还不容易?我就是差点让这个想法给害苦了。
其他的就不多说了,帖出减法的代码:
function Subtr(arg1,arg2){
var r1,r2,m,n
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))
//last modify by deeka
//动态控制精度长度
n=(r1>=r2)?r1:r2
return ((arg1*m-arg2*m)/m).toFixed(n)
}
一直知道js的浮点数计算是不精确的, 0.1 + 0.2 !== 0.3,但是也就知道而已,解决方法却不怎么注意,所以刚做一个项目,尽管了解浮点数精度不精确的问题,但是还是掉坑里了。在此再次默默告诉自己要警惕,端正心态,不可掉以轻心!!!所以下面就分享一些加减乘除的方法。
原理: 把数字转换成字符串,然后从小数点部分切割成两部分,分别算出两个因数的小数点右边的长度,然后用两个因数的小数点右边长度最大的数再乘以10,相当于两个都放大了n倍,然后相加,然后缩小n倍。
注意,这里的放大用了乘法times函数(下面介绍),因为浮点数直接乘以100有可能出现精度不够的情况,如下图
原理和加法一样,放大n倍后相减再缩小n倍
乘法原理稍微变点,放大倍数n是 ‘两个小数点后面长度之和’ 而不是 ‘两个小数点后面长度这两者之间的最大值’
除法原理和乘法一样
这也是一个坑,比如你要保留两位小数,四舍五入的话就要看小数点第三位后面的数字来决定,如2.445四舍五入后就是2.45; 2.444四舍五入就是2.44;做这个需求的时候,我第一反应是Math.toFixed(2),结果是bug百出啊,这里就不举例了,有兴趣可以自己尝试。然后我是怎么解决的呢?百度了一下,也是得到一些半成品不严谨的函数,原理也很简单,先放大倍数,然后利用Math.round()取整
以上加减乘除方法基本满足一般业务需求了,尤其是电商。但是如果数字计算时超出了 2的1024次方减1 ,也就是 9007199254740992 这个数字的话就不适合了,因为从 2^1024 开始就变成了 Infinity。