
正文
javascript浮点,js 浮动
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
js中浮点计算错误原因及解决办法
经典的好家伙(典型的错误):
借用大佬的方法(原理是将浮点数变为整数,之所以用这位大佬,是因为他包含了对超大值的判断 即56.3e-12)
错误原因:因为使用了IEEE754数值,这种错误并非js独有,其他使用相同格式的语言也有这个问题(如c,java,python等)
相关问答
Q1: javascript怎么解决浮点数计算不精确的问题
Math.add = function(v1, v2)
{
///summary精确计算加法。语法:Math.add(v1, v2)/summary
///param name="v1" type="number"操作数。/param
///param name="v2" type="number"操作数。/param
///returns type="number"计算结果。/returns
var r1, r2, m;
try
{
r1 = v1.toString().split(".")[1].length;
}
catch (e)
{
r1 = 0;
}
try
{
r2 = v2.toString().split(".")[1].length;
}
catch (e)
{
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
return (v1 * m + v2 * m) / m;
}
Number.prototype.add = function(v)
{
///summary精确计算加法。语法:number1.add(v)/summary
///param name="v" type="number"操作数。/param
///returns type="number"计算结果。/returns
return Math.add(v, this);
}
Math.sub = function(v1, v2)
{
///summary精确计算减法。语法:Math.sub(v1, v2)/summary
///param name="v1" type="number"操作数。/param
///param name="v2" type="number"操作数。/param
///returns type="number"计算结果。/returns
return Math.add(v1, -v2);
}
Number.prototype.sub = function(v)
{
///summary精确计算减法。语法:number1.sub(v)/summary
///param name="v" type="number"操作数。/param
///returns type="number"计算结果。/returns
return Math.sub(this, v);
}
Math.mul = function(v1, v2)
{
///summary精确计算乘法。语法:Math.mul(v1, v2)/summary
///param name="v1" type="number"操作数。/param
///param name="v2" type="number"操作数。/param
///returns type="number"计算结果。/returns
var m = 0;
var s1 = v1.toString();
var s2 = v2.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.prototype.mul = function(v)
{
///summary精确计算乘法。语法:number1.mul(v)/summary
///param name="v" type="number"操作数。/param
///returns type="number"计算结果。/returns
return Math.mul(v, this);
}
Math.div = function(v1, v2)
{
///summary精确计算除法。语法:Math.div(v1, v2)/summary
///param name="v1" type="number"操作数。/param
///param name="v2" type="number"操作数。/param
///returns type="number"计算结果。/returns
var t1 = 0;
var t2 = 0;
var r1, r2;
try
{
t1 = v1.toString().split(".")[1].length;
}
catch (e)
{
}
try
{
t2 = v2.toString().split(".")[1].length;
}
catch (e)
{
}
with (Math)
{
r1 = Number(v1.toString().replace(".", ""));
r2 = Number(v2.toString().replace(".", ""));
return (r1 / r2) * pow(10, t2 - t1);
}
}
Number.prototype.div = function(v)
{
///summary精确计算除法。语法:number1.div(v)/summary
///param name="v" type="number"操作数。/param
///returns type="number"计算结果。/returns
return Math.div(this, v);
}
Q2: js浮点数的比较方法
正常的比较浮点数大小会出现偏差,因为精度的问题会导致 0.1+0.2 不等于 0.3 ,所以无法用 == 或者 === 做比较,可以采用下面的方式判断是否相等,判断差值是否小于最小精度值
Q3: JS实现浮点数精确舍入小数点
舍入是使用数字时最常见的操作之一。
这里有几个对数字进行舍入的内建函数:
//向下舍入:3.1变成3,-1.1变成-2
//向上舍入:3.1变成4,-1.1变成-1
//向最近的整数舍入:3.1变成3,3.6变成4,中间值3.5变成4
//移除小数点后的所有内容而没有舍入:3.1变成3,-1.1变成-1
这些函数涵盖了处理数字小数部分的所有可能方法。但是,如果我们想将数字舍入到小数点后 n 位改怎么办?
例如,我们有 1.2345 ,并且想把它舍入到小数点后两位,仅得到 1.23 。
有两种方法可以实现这个需求:
1.乘除法
例如,要将数字舍入到小数点后两位,我们可以将数字乘以 100 (或更大的 10 的整数次幂),调用舍入函数,然后再将其除回。
2.函数 toFixed(n) 将数字舍入到小数点后 n 位,并以字符串形式返回结果。
这会向上或向下舍入到最接近的值,类似于Math.round():
请注意 tofixed 的结果是一个字符串。如果小数部分比需要的短,则在结尾添加 0 :
我们可以使用一元加号或 Number() 调用,将其转换为数字: +num.toFixed(5) ;
Q4: js浮点数的加减乘除解决方案
一直知道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。
Q5: JavaScript为什么浮点数会丢失精度
JS浮点计算问题
问题
用js进行浮点数计算,结果可能会“超出预期”,大部分计算结果还是对的,但是我们可不想在计算这么严谨的事情上还有意外的惊喜。比如:
0.3 + 0.6 = 0.8999999999999999
0.3 - 0.2 = 0.09999999999999998
0.3 * 1.5 = 0.44999999999999996
0.3 / 0.1 = 2.9999999999999996
看完这几个计算结果,如果你没用过js,你可能会有点崩溃。我只能说,这就是js的魅力所在。
分析
在这之前,你需要知道以下几点:
js中数字类型只有Number;
js的Number是IEEE 754标准的64-bits的双精度数值
网上有很多关于此问题的解释,由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而js中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失。其实高级语言(c#,java)也存在此问题,只不过它们自己内部做了处理,把这种精度差异给屏蔽掉了。有些小数转换为二进制位数是无穷的(有循环),但是64位中小数最多只有52位,因此对于位数超过的相当于被截取了,导致了精度的丢失。这个地址可以用来浮点数和IEEE 754标准的64-bits的互转(背后是二进制的转换),用这个我们来验证下0.3-0.2。
0.3转换后为0.299999999999999988897769753748
0.2转换后为0.200000000000000011102230246252
0.299999999999999988897769753748-0.200000000000000011102230246252=0.099999999999999977795539507496
这和js直接计算的结果0.09999999999999998想吻合。
分析下来,终于明白并不是js自身发育不良,只是没有及时补充营养,我们只能另想出路了。
以上是网上找的
我以前遇到过问题2中浏览器计算的结果 是两种,所以和浏览器也有问题







