Vue或JS的浮点型乘除法无法精确计算

摘要:
最近,在做购物车时,我遇到了浮点乘除法无法精确计算的问题。在计算产品价格时,JS浮点数的精度问题经常出现。这个问题对于财务管理系统的开发者来说是一个非常严重的问题。在这里,我将整理出问题的原因和解决方法,希望能为大家提供一些参考。

最近做购物车时,遇到了浮点型乘除法无法精确计算,涉及到产品价格的计算,经常会出现JS浮点数精度问题,这个问题,对于财务管理系统的开发者来说,是个非常严重的问题(涉及到钱相关的问题都是严重的问题),这里把相关的原因和问题的解决方案整理一下,也希望给各位提供一些参考。

一. 常见例子  

// 加法
0.1 + 0.2 = 0.30000000000000004
0.1 + 0.7 = 0.7999999999999999
0.2 + 0.4 = 0.6000000000000001
 
// 减法
0.3 - 0.2 = 0.09999999999999998
1.5 - 1.2 = 0.30000000000000004
 
// 乘法
0.8 * 3 = 2.4000000000000004
19.9 * 100 = 1989.9999999999998
 
// 除法
0.3 / 0.1 = 2.9999999999999996
0.69 / 10 = 0.06899999999999999
 
// 比较
0.1 + 0.2 === 0.3 // false
(0.3 - 0.2) === (0.2 - 0.1) // false

二. 导致原因

下面我们来说一下浮点数运算产生误差的原因:(拿0.1+0.2=0.30000000000000004进行举例)

首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:  

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

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

上面我们发现0.1和0.2转化为二进制之后,变成了一个无限循环的数字,这在现实生活中,无限循环我们可以理解,但计算机是不允许无限循环的,对于无限循环的小数,计算机会进行舍入处理。进行双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 ,因浮点数小数位的限制而截断的二进制数字这时候,我们再把它转换为十进制,就成了0.30000000000000004

三. 解决方法

Vue浮点型乘法:

Vue.prototype.NumberMul = function(arg1, arg2) {
    var m = 0;
    var s1 = arg1.toString();
    var 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);
}

Vue浮点型加法:

Vue.prototype.NumberAdd = function(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 ((arg1 * m + arg2 * m) / m).toFixed(n);
}

Vue浮点型减法:

Vue.prototype.NumberSub = function(arg1, arg2) {
    var re1, re2, m, n;
    try {
        re1 = arg1.toString().split(".")[1].length;
    } catch (e) {
    re1 = 0;
    }
    try {
        re2 = arg2.toString().split(".")[1].length;
    } catch (e) {
        re2 = 0;
    }
    m = Math.pow(10, Math.max(re1, re2)); 
    n = (re1 >= re2) ? re1 : re2;
    return ((arg1 * m - arg2 * m) / m).toFixed(n);
}

Vue浮点型除法:

// 除数,被除数, 保留的小数点后的位数
Vue.prototype.NumberDiv = function (arg1,arg2,digit){
    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){}
    r1=Number(arg1.toString().replace(".",""))
    r2=Number(arg2.toString().replace(".",""))
    //获取小数点后的计算值
   var result= ((r1/r2)*Math.pow(10,t2-t1)).toString()
    var result2=result.split(".")[1];
    result2=result2.substring(0,digit>result2.length?result2.length:digit);
 
    return Number(result.split(".")[0]+"."+result2);
}

使用的话也很简单(乘法计算

{{NumberMul(0.0058,100)}}

如果是JS的话,也可以这样使用:

var NumberMul = function(arg1, arg2) {
    var m = 0;
    var s1 = arg1.toString();
    var 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);
}

原文链接:https://blog.csdn.net/m0_37948170/article/details/88237208

免责声明:文章转载自《Vue或JS的浮点型乘除法无法精确计算》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇virtualbox结合nat和host-only设置固定ip的环境IDEA 中.properties文件中文自动转Unicode编码及乱码问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java 基础 AutoCloseable & Closeable

Overview Closeable和AutoCloseable都是接口,且都只定义了一个close()方法。Closeable: 定义于 java.io包中,于JDK5添加;AutoCloseable: 定义于java.lang包中, 于JDK7添加; AutoCloseable.java public interface AutoCloseable{...

IO操作

IO流 1.IO用来处理设备之间的数据传输2.Java对数据的操作通过流的方式3.Java用于操作流的对象都在IO中4.流操作数据分两种,字节流和字符流5.流按流向可以分为:输入流和输出流 IO流常用基类 字节流的抽象基类InputStream OutputStream 字符流的抽象基类Reader Writer 注:由这四个派生出来额子类名称都是以其父类...

java,c,c++ 语言之间基本数据类型的比较

当要进行底层移植的时候肯定会遇到这些问题。特整理了下。 java语言基本数据类型   在JAVA中一共有八种基本数据类型,他们分别是 byte、short、int、long、float、double、char、boolean 整型 其中byte、short、int、long都是表示整数的,只不过他们的取值范围不一样 byte的取值范围为-1...

java 如何在pdf中生成表格

1、目标   在pdf中生成一个可变表头的表格,并向其中填充数据。通过泛型动态的生成表头,通过反射动态获取实体类(我这里是User)的get方法动态获得数据,从而达到动态生成表格。   每天生成一个文件夹存储生成的pdf文件(文件夹的命名是年月日时间戳),如:20151110   生成的文件可能在毫秒级别,故文件的命名规则是"到毫秒的时间戳-uuid",如...

Vue前端实现登陆功能

在登陆组件中找到登陆按钮,绑定点击事件 <button @click="loginhander">登录</button> 在methods中请求后端 export default { name: 'Login', data(){ return { login_type: 0, r...

Vue3.0 全面探索 基于 Visual Studio Code 的代码片段开发插件

Vue3 Snippets for Visual Studio Code Vue3 Snippets源码 Vue3 Snippets下载 This extension adds Vue3 Code Snippets into Visual Studio Code. 这个插件基于最新的 Vue3 的 API 添加了 Code Snippets。 Snip...