js浮点数精度丢失问题及如何解决js中浮点数计算不精准

js中进行数字计算时候,会出现精度误差的问题。先来看一个实例:

console.log(0.1+0.2===0.3);//false

console.log(0.1+0.1===0.2);//true

上面第一个的输出会超出我们的常识,正常应该为true,这里为什么会是false呢,直接运行会发现0.1+0.2在js中计算的结果是:

console.log(0.1+0.2);//输出0.30000000000000004

这对于浮点数的四则运算(加减乘除),几乎所有的编程语言都会出现上面类似的精度误差问题,只是大部分语言都处理封装了避免误差的方法。对于js而言,由于它是一门弱类型的语言,所以并没有对浮点数的运算有解决的封装方法,这能我们自己来解决。这里为什么会出现这个精度误差呢?

浮点数产生的原因 

我们首先就想到计算机能读懂的是二进制,所以我们进行运算的时候,实际上是把数字转换为了二进制进行的,所以我们把0.1和0.2转换为二进制:

0.1 => 0.0001 1001 1001 1001..(无限循环)

0.2 => 0.0011 0011 0011 0011…(无限循环)

这里可以看出转换为二进制是一个无限循环的数字,单在计算机中对于无限循环的数字会进行舍入处理的,进行双精度浮点数的小数部分最多支持52位。然后把两个2进制的数进行运算得出的也是一个二进制数值,最后再把它转换为十进制。保留17位小数,所以0.1+0.2的值就成了 0.30000000000000004。  0.1+0.1的值成了0.20000000000000000,全是0的时候可以省略,就成了0.2

解决浮点数精度误差的办法

最简单的处理,通过toFixed方法,

console.log(parseFloat(0.1+0.2).toFixed(1));//输出0.3

说明:通过toFixed(num)方法来保留小数,其中num为保留小数的位数,这个方法是根据四舍五入来保留小数的,所以计算的结果并不是最精确的。所以我们需要采用其它方法来实现,通过Number.prototype的属性进行添加,如下:

js加法:

//加法函数

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方法,使用时直接用 .add 即可完成计算。

Number.prototype.add = function(arg){

return accAdd(arg, this);

};

console.log(0.1.add(0.2).add(0.3));//等价于0.1+0.2+0.3,输出0.6

console.log(0.1+0.2+0.3);//输出0.6000000000000001

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)); //动态控制精度长度

n = (r1 >= r2) ? r1 : r2;

return parseFloat(((arg1 * m - arg2 * m) / m).toFixed(n));

}

Number.prototype.sub = function(arg) {

return Subtr(this, arg);

};

console.log(0.6.sub(0.2).sub(0.3));//等价于0.6-0.2-0.3 输出0.1

console.log(0.6-0.2-0.3);//输出:0.09999999999999998

js乘法:

//乘法函数

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.prototype.mul = function (arg) {

return accMul(arg, this);

};

console.log(0.1.mul(0.2).mul(0.3)); //等价于0.1 * 0.2 * 0.3 输出0.006

console.log(0.1 * 0.2 * 0.3); //输出:0.006000000000000001

js除法:

//除法函数

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.prototype.div = function (arg) {

return accDiv(this, arg);

};

console.log(0.6.div(0.2).div(0.1)); //等价于0.6 / 0.2 / 0.1 输出30

console.log(0.6 / 0.2 / 0.1); //输出:29.999999999999993

原文地址:https://www.cnblogs.com/ranyonsue/p/11378200.html

时间: 2024-11-05 06:25:41

js浮点数精度丢失问题及如何解决js中浮点数计算不精准的相关文章

Java 浮点数精度丢失

Java 浮点数精度丢失 问题引入 昨天帮室友写一个模拟发红包抢红包的程序时,对金额统一使用的 double 来建模,结果发现在实际运行时程序的结果在数值上总是有细微的误差,程序运行的截图: 输入依次为:红包个数,抢红包的人数,选择固定金额红包还是随机金额红包,每个红包的金额(此例只有一个红包). 注意到程序最后的结果是有问题的,我们只有一个金额为 10 的红包,一个人去抢,所以正确结果应该为这个人抢到了 10 RMB. 为了使问题更加明显,我们测试一个更加简单的例子: public class

javascript(js)小数精度丢失的解决方案

原因:js按照2进制来处理小数的加减乘除,在arg1的基础上 将arg2的精度进行扩展或逆扩展匹配,所以会出现如下情况. javascript(js)的小数点加减乘除问题,是一个js的bug如0.3*1 = 0.2999999999等,下面列出可以完美求出相应精度的四种js算法 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].length}catch(e){} t

长整型Long返回到前端,js出现精度丢失怎么办

前端后接口对接时,如果后台的id或者其他字段使用了长整型Long,就很容易出现js丢失精度问题.用接口工具调用时,往往id返回都是对的,但是一到页面上,js就后缀000.前端说返回的值有问题,F12看看!后端说没问题,Postman看看!这是js支持的问题,解决这个问题的办法很显然,返回字符串即可.怎么实现呢,你可以直接将vo对象的id改成String类型,但是会带来copyProperties的不便,所以见过很多人通过增加虚拟字段实现.下面是一个整体解决方案:(需要略微了解下Spring的消息

JavaScript数字精度丢失问题总结

本文分为三个部分 JS 数字精度丢失的一些典型问题 JS 数字精度丢失的原因 解决方案(一个对象+一个函数) 一.JS数字精度丢失的一些典型问题 1. 两个简单的浮点数相加 0.1 + 0.2 != 0.3 // true Firebug 这真不是 Firebug 的问题,可以用alert试试 (哈哈开玩笑). 看看Java的运算结果 再看看Python 2. 大整数运算 9999999999999999 == 10000000000000001 // ? Firebug 16位和17位数竟然相

javascript解决小数的加减乘除精度丢失的方案

原因:js按照2进制来处理小数的加减乘除,在arg1的基础上 将arg2的精度进行扩展或逆扩展匹配,所以会出现如下情况. javascript(js)的小数点加减乘除问题,是一个js的bug如0.3*1 = 0.2999999999等,下面列出可以完美求出相应精度的四种js算法 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function acc

[转载]JavaScript 中小数和大整数的精度丢失

标题: JavaScript 中小数和大整数的精度丢失作者: Demon链接: http://demon.tw/copy-paste/javascript-precision.html版权: 本博客的所有文章,都遵守“署名-非商业性使用-相同方式共享 2.5 中国大陆”协议条款. 先来看两个问题: 0.1 + 0.2 == 0.3; // false 9999999999999999 == 10000000000000000; // true 第一个问题是小数的精度问题,在业界不少博客里已有讨论

关于js浮点数计算精度不准确问题的解决办法

今天在计算商品价格的时候再次遇到js浮点数计算出现误差的问题,以前就一直碰到这个问题,都是简单的使用tofixed方法进行处理一下,这对于一个程序员来说是及其不严谨的.因此在网上收集了一些处理浮点数精度的文章.觉得别人写的挺好了,我在简单的总结一下,以方便后续查阅. 浮点数误差产生的原因: 先看一个实例: 0.1 + 0.2 =? 0.1 + 0.2 = 0.3? 我们先来看一段 JS. console.log( 0.1+ 0.2); 输出为 0.30000000000000004.是不是很奇葩

js数字位数太大导致参数精度丢失问题

最近遇到个比较奇怪的问题,js函数里传参,传一个位数比较大,打印arguments可以看到传过来的参数已经改变. 然后查了一下,发现确实是js精度丢失造成的.我的解决方法是将数字型改成字符型传输,这样就不会造成精度丢失了.如下图: JS 数字丢失精度的原因 计算机的二进制实现和位数限制有些数无法有限表示.就像一些无理数不能有限表示,如 圆周率 3.1415926...,1.3333... 等.JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bi

JS浮点计算精度问题分析与解决

问题描述 在JS计算四则运算时会遇到精度丢失的问题,会引起诸多问题,看看以下例子: 例如:在chrome控制台输入 0.1 + 0.7 输出结果是 0.7999999999999999 例如:0.1+0.2 输出结果:0.30000000000000004 例如:0.1277*1000000000000 输出结果:127700000000.00002 问题代码 bMsg.expectRate的值为0.1277 bMsg.expectRate * 1000000000000 / 100000000