zoukankan      html  css  js  c++  java
  • js 浮点型运算出错的原因和解决方法

    在工作中经常需要进行数字运算,当然也会遇到浮点型数字的运算,但是运算结果却并不是想要。

    这种小孩子都会做的简单运算,强大的计算居然算算错?原来,计算机的运算都需要转成二制运算,而二进制和实现位数限制有些数无法有限表示。

    比如:以下是十进制小数对应的二进制表示

    0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
    0.2 >> 0.0011 0011 0011 0011…(0011无限循环
    

    计算机里每种数据类型的存储是一个有限宽度,比如 JavaScript 使用 64 位存储数字类型,因此超出的会舍去。舍去的部分就是精度丢失的部分。

    那小数计算会有问题,那把数字转整数来计算不就可以了吗?

        /* ===== 浮点型数据的加、减、乘、除 ===== */
        function add(arg1, arg2) { // 加法
            let 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
        }
    
        function sub(arg1, arg2) { // 减法
            let 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)
        }
    
       function  mul(arg1, arg2) { // 乘法
            let m = 0
            let s1 = arg1.toString()
            let 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)
        }
    
        function div(arg1, arg2) { // 除法
            let t1 = 0
            let t2 = 0
            let r1
            let 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('.', ''))
            let intDiv = r1 / r2
            let pow = Math.pow(10, t2 - t1)
            return mul(intDiv, pow) // 这里用上面定义好的乘法运算
        }
        /* ===== 浮点型数据的加、减、乘、除 ===== */
    

      

  • 相关阅读:
    第4章-控制执行流程
    第3章-运算符
    第2章-对象
    第10章-内部类II
    第10章-内部类
    基于gtest、gmock、mockcpp和lcov的C语言LLT工程 —— LLT构造和lcov查看覆盖率实例
    字符设备驱动框架讲解
    基于Hadoop分布式集群YARN模式下的TensorFlowOnSpark平台搭建
    给 Virtualbox 中 Ubuntu 系统设置静态 IP
    小白请教几个关于Java虚拟机内存分配策略的问题
  • 原文地址:https://www.cnblogs.com/garfieldzhong/p/11255345.html
Copyright © 2011-2022 走看看