js浮点数运算的坑,多少同学有碰到过?
- javascript中的数字都是双精度的浮点数。
- JavaScript中的整数并不是一个独立的数据类型,而是浮点数的一个子集。
浮点数的坑
我们看下面的例子
在浏览器的console 控制台上我们分别进行以下的浮点数运算

通过控制台的运算,我们可以很惊奇的看到答案,有些运算结果竟然和我们想像的不一样,比如0.1+0.2的返回结果不是0.3,而是0.30000000000000004。
这究竟是啥原因?
1,首先要肯定的是这不是浏览器的问题,而是由于浮点数的精度导致的。
2,浮点数的精度问题并不是JavaScript所独有的,例如在java中,我们运行以下代码,同样会输出和JavaScript中一样的结果。
double dd = 0.1+0.2;
System.out.println(dd);//0.30000000000000004?
why?
因为电脑永远都是按照二进制进行运算的,我们输入的十进制数在转化为二进制数时,并不总如人意,意思是说有些十进制并不能用准确的二进制数表示。
十进制小树转二进制表示
我们来看下十进制小树转二进制表示的过程,小数位乘以2,取整,小数部分继续乘以2,再取整,直到小数部分为0为止,然后将取整位按顺序排列。
由此方法我们可以看到以下一些十进制小数的二进制表示。
十进制 二进制
0.1 0.0001 1001 1001 1001 ...
0.2 0.0011 0011 0011 0011 ...
0.3 0.0100 1100 1100 1100 ...
0.4 0.0110 0110 0110 0110 ...
0.5 0.1
0.6 0.1001 1001 1001 1001 ...
我们发现有些小数的二进制表示位数是无限循环的,这就造成了浮点数精度上的问题。
比如十进制的1.1,在用二进制表示的时因为存在二进制位无限循环的表示,实际值为1.0999999999...无限接近与1.1
解决方案
常用的一种解决方法就是将浮点数转化为整数进行运算,以下是一些封装好的关于浮点运算的方法,而且经过测试,加减乘除运算都会达到自己想要的结果。
//求和
function add(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 Math.round(num1*m + num2*m)/m;
}
//相减
function sub(num1,num2){
var r1,r2,m;
try{
r1 = num1.toString().split('.')[1].length;
}catch(e){
r1 = 0;
}
try{
r2 = num1.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 mul(num1,num2){
var m = 0,r1,r2;
var s1 = num1.toString();
var s2 = num2.toString();
try{
m += s1.split('.')[1].length
}catch(e){ }
try{}catch(e){
m += s2.split('.')[1].length
}catch(e){ }
r1 = Number(num1.toString().replace(".",""));
r2 = Number(num2.toString().replace(".",""));
return r1 * r2 / Math.pow(10,m);
}
//相除
function accDiv(){
var t1,t2,r1,r2;
try{
t1 = num1.toString().split('.')[1].length;
}catch(e){
t1 = 0;
}
try{}catch(e){
t2 = num2.toString().split('.')[1].length;
}catch(e){
t2 = 0;
}
r1 = Number(num1.toString().replace(".",""));
r2 = Number(num2.toString().replace(".",""));
return (r1 / r2)*Math.pwo(10,t2-t1);
}
js浮点数运算的坑,多少同学有碰到过?的更多相关文章
- JS浮点数运算Bug
JS浮点数运算Bug的解决办法(转) 37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.0849999 ...
- JS浮点数运算BUG破法
JS里,0.3*3 = 0.8999999999999999 破法1:((0.3*10)*3)/10 破法2:(0.3*3).toFixed(2)//保留两位小数 原因:js浮点数用的是IEEE754 ...
- js浮点数运算需要注意的问题
最近在js运算浮点数时发现了一个问题.问题是这样的:js函数中处理两个浮点数的相加,为了防止出现0.1+0.2=0.30000000000000004的问题,两个数都先乘以10000后再相加,得到结果 ...
- js浮点数运算封装, 起因财务部分精确计算
目录 背景 具体代码 背景 项目中用到浮点数,Int 等 js中 Number类型比较多, 加上牵涉到财务软件, 前台js运算等. 有时候会出现精确度的问题 , 公共方法中有好事者写的方法. 此处拿来 ...
- 【转】JS浮点数运算Bug的解决办法
37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会这样,两个只有一 ...
- 记C语言浮点数运算处理 "坑" 一则
看一小段C语言程序: int main() { float x = 1.3; x = x - (int)x; ); ; } 在你心目中, 变量 I 是怎样的结果? 如果你理所当然地认为是3的话, 那么 ...
- JS浮点数运算Bug的解决办法
方法一:重写浮点运算的函数 //除法函数,用来得到精确的除法结果 //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显.这个函数返回较为精确的除法结果. //调用:acc ...
- JS浮点数运算
//乘法函数,用来得到精确的乘法结果 //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显.这个函数返回较为精确的乘法结果. //调用:accMul(arg1,arg2) ...
- js浮点数运算出现误差解决方案
1.数据展示类(使用 toPrecision 凑整并 parseFloat 转成数字后再显示) parseFloat(1.4000000000000001.toPrecision(12)) === 1 ...
随机推荐
- Linux显示指定区块大小为1048576字节
Linux显示指定区块大小为1048576字节 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ df -m 文件系统 1M-blocks 已用 可用 已用% 挂 ...
- “net usershare”返回错误 255
1 错误描述 youhaidong@youhaidong:~$ sudo nautilus (nautilus:4429): Gtk-WARNING **: Failed to register cl ...
- spoj freetour II
昨天吐槽还没A,今天就A了 有个变量开成了全局变量,应该携程局部变量 对于中间的solve我也不懂为什么是nlog2n,我不看题解也不会做 #include<bits/stdc++.h> ...
- 非空校验的提示按钮(shiro项目中来的六)
一:图示 二,js脚本 /** * jquery tips 提示插件 jquery.tips.js v0.1beta * * 使用方法 * $(selector).tips({ //selector ...
- Struts2入门这一篇就够了
前言 这是Strtus的开山篇,主要是引入struts框架...为什么要引入struts,引入struts的好处是什么,以及对Struts2一个简单的入门.... 为什么要引入struts? 既然Se ...
- SpringBoot 文件上传临时文件路径问题
年后放假回来,一向运行OK的项目突然图片上传不了了,后台报错日志如下: java.io.IOException: The temporary upload location [/tmp/tomcat. ...
- java继承方法规则或规律
方法的继承与属性的继承有很大的不同,属性任何继承方式均可,而方法则有各种限制,于是在这里做了一个简单的总结: 1.修饰符相同的方法覆盖,即只改内部,不改外部 2.访问权限不同的方法覆盖,子类只能相对父 ...
- Js表单验证控件(使用方便,无需编码)-01使用说明
演示地址:http://weishakeji.net/Utility/Verify/Index.htm 开源地址:https://github.com/weishakeji/Verify_Js ...
- webstorm提交版本时,忽略特定文件
项目提交时,部分本地配置文件,不需要提交,这时候需要在整个版本控制中忽略掉文件的提交. 操作如下: File -> Settings -> Version Control -> Ig ...
- border-image的拉伸和平铺
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...