大学专业是计算机童鞋或多或小的知道 计算机是由二进制存储和处理数字的,不能精确到处理浮点数,且javascript也没有这样的方法 所以在浏览器计算的时候也会有误差,比如说 我想用 3.3 / 1.1  那么按道理来说 答案是 3 ,对不对 但是我们可以打印出来看下 结果令我们很惊讶 是 2.9999999999999996 .现在我们想 为了避免产生精度差异,需要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,等计算完毕再降级(除以10的n次幂). 这样处理下 就可以实现正常的结果。

基本原理:

   需要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,等计算完毕再降级(除以10的n次幂). 这样处理下 就可以实现正常的结果。

Javascript 如何解决对 "加法" 精度问题

其实不管对于 加法,减法 乘法及除法也好 其基本原理都是一样 先乘以10的n次幂 成计算机能够识别的整数 然后计算 计算完成后 再除以10的n次幂 这样就可以得到想要的结果。

   现在我们先列举个列子 比如:var a = 1.3, b = 2.3;那么 我通过在火狐浏览器打印一下console.log(a+b)=? 结果在火狐浏览器下看到等于:3.5999999999999996 .这也就是说计算机对浮点计算存在精度问题。而现在我们想写个js函数方法,来避免这种情况的产生。

   函数的基本原理:先传入2个参数 分别为arg1,arg2;先判断下 如果2个参数都是浮点数的话 那么取得该2个参数的小数点后面的长度,分别保存到变量为firstArg,lastArg; 否则的话 如果那个参数不是浮点的话 那么让此fisrtArg或者lastArg赋值为0. 然后取得差值 differ = Math.abs(firstArg - lastArg).(目的是为了下面判断他们的小数点位数是否相同。) 接着获取最大的n次幂 如: m = Math.pow(10,Math.max(firstArg,lastArg));

   1. 接着上面的话说,如果小数点后面的位数长度相同的话 比如说 1.3 和 2.3 小数点后的数字都是3,那么他们的长度都是相同的的(为1).那么先变为整数 去掉小数点后计算 如:arg1 = Number(arg1.toString().replace(".", ""));arg2 = Number(arg2.toString().replace(".", "")); 然后接着再除以他们的n次幂 如:return (arg1 + arg2) / m; 这样可以返回结果。

   2. 如果小数点后面的位数长度不一致的话 先通过他们的差值 differ获取n次幂 如:var dm = Math.pow(10,differ); 再判断 如果 firstArg > lastArg 那么 arg1 = Number(arg1.toString().replace(".", "")); arg2 = Number(arg2.toString().replace(".", "")) * dm;否则的话 arg1 = Number(arg1.toString().replace(".", "")) * dm; arg2 = Number(arg2.toString().replace(".", "")); 再比如:var a = 1.31,b = 2.3; 那么 firstArg的长度为2 lastArg长度为1;因为 2 > 1 那么 arg1 = 131; arg2 = 23 * dm(如上:dm = Math.pow(10,differ));最后计算如:return (arg1 + arg2) / m --> (arg1 + arg2) / m  ---> (131 + 23*10) / Math.pow(10,Math.max(firstArg,lastArg)); --> 

 (131 + 230) / Math.pow(10,2) --> 361 / 100 = 3.61; 和1.31 + 2.3 结果一致。同理firstArg < lastArg也是一样的原理。这里不多说了。

 为了更详细的说明问题 我们可以先来看看流程图:如下:

  

下面是JS函数代码如下:

/**
* js加法 解决精度问题
*/ function addFun(arg1,arg2) {
var firstArg,
lastArg,
differ,
m;
try{
firstArg = arg1.toString().split('.')[1].length;
}
catch (e){
firstArg = 0;
} try{
lastArg = arg2.toString().split('.')[1].length;
}
catch (e){
lastArg = 0;
}
differ = Math.abs(firstArg - lastArg);
m = Math.pow(10,Math.max(firstArg,lastArg)); if(differ > 0) {
var dm = Math.pow(10,differ);
if(firstArg > lastArg) {
arg1 = Number(arg1.toString().replace(".", ""));
arg2 = Number(arg2.toString().replace(".", "")) * dm; }else {
arg1 = Number(arg1.toString().replace(".", "")) * dm;
arg2 = Number(arg2.toString().replace(".", ""));
}
}else {
arg1 = Number(arg1.toString().replace(".", ""));
arg2 = Number(arg2.toString().replace(".", ""));
}
return (arg1 + arg2) / m;
}

Javascript 如何解决对 "减法" 精度问题

同样现在我们先列举个列子 比如:var a = 1.3, b = 2.3;那么 我通过在火狐浏览器打印一下console.log(b-a)=? 结果在火狐浏览器下看到等于:0.9999999999999998.同样我们想写个js函数方法,来避免这种情况的产生

代码实现原理是:先传入2个参数 分别为arg1,arg2;先判断下 如果2个参数都是浮点数的话 那么取得该2个参数的小数点后面的长度,分别保存到变量为firstArg,lastArg; 否则的话 如果那个参数不是浮点的话 那么让此fisrtArg或者lastArg赋值为0. 然后获取他们的最大n次幂如:

differ = Math.pow(10, Math.max(firstArg, lastArg)); 接着如下判断 如果firstArg的长度大于lastArg的长度 那么返回firstArg,否则返回lastArg; 如:m = (firstArg > lastArg) ? firstArg : lastArg;最后返回 return ((arg1 * differ - arg2 * differ) / differ).toFixed(m); 接着再列举列子 比如还是上面 传入a=2.3, b = 1.3 那么他们的长度相等(都为1) 即:differ = Math.pow(10,1);

m = lastArg = 1; 最后返回 ((arg1 * differ - arg2 * differ) / differ).toFixed(m) --> (2.3*10 - 1.3*10)/10.toFixed(1) = 1.0;

接着我们可以再列举个反列:比如var b = 2.31, a = 1.3; 那么他们的长度不相等 即(b的小数点后面的长度为2 > a的小数点后面的长度1) 那么differ = Math.pow(10,Math(firstArg,lastArg)) -- > differ = Math.pow(10,2) --> differ = 100; m = firstArg = 2; 最后返回

((arg1*differ - arg2*differ)/differ).toFixed(m) --> (2.31*100 -1.3 * 100)/100.toFixed(2) = ((231-130)/100).toFixed(2) = 1.01; 和 b -a = 2.31 - 1.3 = 1.01结果相同 同样推理正确。同样我们来个简单流程图 如下:

 

下面是JS对减法解决精度的函数方法代码如下:

/*
* JS减法 解决精度问题
*/ function subtraction(arg1,arg2){
var firstArg,
lastArg,
differ,
m;
try{
firstArg = arg1.toString().split('.')[1].length;
}catch (e){
firstArg = 0;
} try{
lastArg = arg2.toString().split('.')[1].length;
}
catch (e){
lastArg = 0;
}
differ = Math.pow(10, Math.max(firstArg, lastArg));
m = (firstArg > lastArg) ? firstArg : lastArg;
return ((arg1 * differ - arg2 * differ) / differ).toFixed(m);
}

Javascript 如何解决对 "乘法" 精度问题

同样现在我们先列举个列子 比如:var a = 1.3, b = 2.3;那么 我通过在火狐浏览器打印一下console.log(a*b)=? 结果在火狐浏览器下看到等于:2.9899999999999998.但是实际的结果是:2.99 同样我们想写个js函数方法,来避免这种情况的产生.

  代码的实现原理是:先传入2个参数 分别为arg1,arg2,先把这2个参数转化为字符串分别保存到firstArg和lastArg里面,如:

  firstArg = arg1.toString();lastArg = arg2.toString(); 接着定义个变量 m = 0;然后分别取到firstArg,lastArg的长度与m分别相加,如:m += firstArg.split('.')[1].length; m += lastArg.split('.')[1].length; 也就是说 m得到的就是 后面的小数点的位数。最后如下返回 return Number(firstArg.replace(".", "")) * Number(lastArg.replace(".", "")) / Math.pow(10, m);

  比如再列举个列子 还是刚刚 a = 1.3, b = 2.3 来讲,因为他们的firstArg和lastArg的长度都为1,也就是说 m = 2;那么返回

  Number(firstArg.replace(".", "")) * Number(lastArg.replace(".", "")) / Math.pow(10, m) ---> 

  Number(13 * 23)/Math.pow(10,2) = 13*23 / 100 = 2.99 与我们的1.3×2.3 = 2.99 结果相同。同理我们也可以随便列举列子都可以的,在这就不一一列举哦!有兴趣的童鞋可以多列举下。

实现的JS代码如下:

/**
* JS乘法 解决精度问题
*/
function multiplication(arg1,arg2) {
var m = 0,
firstArg,
lastArg;
firstArg = arg1.toString();
lastArg = arg2.toString(); try{
m += firstArg.split('.')[1].length;
}
catch (e){} try{
m += lastArg.split('.')[1].length;
}
catch (e){} return Number(firstArg.replace(".", "")) * Number(lastArg.replace(".", "")) / Math.pow(10, m);
}

Javascript 如何解决对 "除法" 精度问题

同样现在我们先列举个列子 比如:var a = 1.1, b = 3.3;那么 我通过在火狐浏览器打印一下console.log(b/a)=? 结果在火狐浏览器下看到等于:2.9999999999999996.但是实际的结果是:3 同样我们想写个js函数方法,来避免这种情况的产生.

代码实现的原理:先传入2个参数 分别为arg1,arg2;先判断下 如果2个参数都是浮点数的话 那么取得该2个参数的小数点后面的长度,分别保存到变量为firstArg,lastArg; 否则的话 如果那个参数不是浮点的话 那么让此fisrtArg或者lastArg赋值为0. 接着把小数点都去掉分别进行相应的运算:如 r1 = Number(arg1.toString().replace(".", ""));r2 = Number(arg2.toString().replace(".", ""));

那么返回如下:return (r1 / r2) * Math.pow(10, lastArg - firstArg);就可以了。

 接着再列举列子 比如var b = 3.3,a = 1.1 那么firstArg和lastArg的长度都为1,那么 r1 = Number(arg1.toString().replace(".", "")); --> r1 = 33; r2 = Number(arg2.toString().replace(".", "")); --> r2 = 11;那么 返回是:

 return (r1 / r2) * Math.pow(10, lastArg - firstArg); --> (33/11)×Math.pow(10,0) = 3.和我们想要等到的结果3.3/1.1=3是一样的,说明推理正确。同样我们可以列举个其他的列子都ok的 具体的可以自己去列举下 这里也不一一列举了。

JS解决对"除法"精度问题的函数代码如下:

/*
* JS除法 解决精度问题
*/
function division(arg1,arg2) {
var firstArg,
lastArg,
r1,
r2; try{
firstArg = arg1.toString().split(".")[1].length;
}
catch (e){
firstArg = 0;
} try{
lastArg = arg2.toString().split('.')[1].length;
}
catch (e){
lastArg = 0;
}
r1 = Number(arg1.toString().replace(".", ""));
r2 = Number(arg2.toString().replace(".", "")); return (r1 / r2) * Math.pow(10, lastArg - firstArg);
}

关于javascript中对浮点加,减,乘,除的精度分析的更多相关文章

  1. Linux中日期的加减运算

    Linux中日期的加减运算 目录 在显示方面 在设定时间方面 时间的加减 正文 date命令本身提供了日期的加减运算. date 可以用来显示或设定系统的日期与时间. 回到顶部 在显示方面 使用者可以 ...

  2. oracle 中日期的加减

    oracle 中日期的加减 加法   select sysdate,add_months(sysdate,12) from dual;        --加1年 select sysdate,add_ ...

  3. C语言中的指针加减偏移量

    C语言指针偏移技巧(也是一个要注意的坑) - 陈杰柱的博客 - CSDN博客  https://blog.csdn.net/cjzjolly/article/details/82116772 C语言中 ...

  4. Js中处理日期加减天数

    Js的处理日期还是很方便的. 一. 格式化日期为2017-07-04的格式 function formatTime(date) { var year = date.getFullYear(); var ...

  5. C语言中指针的加减运算

    参考文章,值得一看 char arr[3]; printf("arr:\n%d\n%d\n%d\n", arr, arr + 1, arr + 2); char *parr[3]; ...

  6. Oracle中的日期加减

    加法   select sysdate,add_months(sysdate,12) from dual;        --加1年 select sysdate,add_months(sysdate ...

  7. PHP中的日期加减方法示例

    几乎所有从事程序开发的程序员都遇到时间处理问题,PHP开发也一样,幸运的是PHP提供了很多关于日期时间函数.只要经常使用这些函数,搭配使用,日期时间处理上就熟能生巧了. 今天要讲的这个例子,需求是这样 ...

  8. mysql中使用日期加减时无法识别年-月格式数据的问题,%Y-%m"这种格式数据

    最新做报表统计的时候处理按月统计部分时发现,虽然使用 DATE_FORMAT( time, '%Y-%m' ) 函数可以将日期格式转成年-月,但是如果是参数是年-月格式,即"2018-10& ...

  9. Java 中 日期 时间 加减

    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //方法1(推荐,功能强大灵活多变) Ca ...

随机推荐

  1. windows下给redis添加密码

    在redis的安装目录下找到 redis.windows-service.conf 文件.用文本编辑器打开, 找到requirepass所在行,回车另起一行,输入requirepass 你的密码, # ...

  2. Docker入门及基本指令

    Docker概念 Docker就相当于一个Github账号,不过最开始的工程不能自己建立,要从DockerHub这个中央仓库pull过来,这个工程Docker称之为image,这个image竟然是个l ...

  3. 第三十天- 进程 Process模块 空间隔离

    1.进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体: ...

  4. selector设置按钮或者一些点击控件在点击时的效果

    <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="ht ...

  5. 百度Ocr文字识别

    简述 最近开发一个项目需要用到Ocr文字识别技术来识别手写文字,在评估过程中体验了百度的文字识别和腾讯的文字识别.查找官方开发文档,发现它们都有印刷体和手写体两种符合项目需求的识别模式,但是腾讯的手写 ...

  6. 大数据【五】Hive(部署;表操作;分区)

    一 概述 就像我们所了解的sql一样,Hive也是一种数据仓库,不同的是hive是在hadoop大数据生态圈中所用.这篇博客我主要介绍Hive的简单表运用. Hive是Hadoop 大数据生态圈中的数 ...

  7. Android--自定义控件---自动分页的GridView

    最近,根据项目需求,需要一个能够自动分页的导航,所以便自定义了一个自动分页的GridView. 思路:继承RelativeLayout,然后在里面放了一个viewpager和一个GridView... ...

  8. 关于win10下JDK环境变量的配置以及关于JDK的一些说明

    一.JDK的下载和安装 这里提供32位和64位JDK的下载链接 百度网盘:https://pan.baidu.com/s/1xtiVOE2gPCvlGCTy0vfBaw 密码:c5m4   官网:ht ...

  9. 解释JS变量作用域的范例

    JS的变量作用域只有两种:全局作用域与函数作用域. 用var声明的变量不能简单的说是属于函数作用域,应该是说属于其最近的作用域. var a = 10; function test(){ var a; ...

  10. Java 如何启用 ARM 虚拟机诊断

    现象描述 如何通过 Java 语言实现在创建 ARM 虚拟机时开启诊断,并配置相关指标.   实现思路 调研最高版本的 JAVA SDK(1.1.0)源码发现,SDK 层面并未提供任启动诊断和配置诊断 ...