龙空技术网

JavaScriptr手册(001)- JS浮点运算精度丢失的问题

宙冰 152

前言:

此刻小伙伴们对“js精度要求”大约比较珍视,同学们都想要了解一些“js精度要求”的相关内容。那么小编也在网摘上汇集了一些关于“js精度要求””的相关资讯,希望大家能喜欢,同学们快快来学习一下吧!

遇到的问题

今天在工作中遇到一个浮点运算后精度丢失的问题,明明两个浮点数相加后是一样的,但是在比较的时候为false,比如0.1+0.2==0.3就为false,查了相关资料才发现0.1+0.2由于js的默认浮点运算的问题导致为:0.30000000000000004,这与0.3比较肯定为false啊

由于JS对于整数运算出错的几率比较小,把所有的浮点数转换成整数进行四则运算,然后再加上对应的小数位就可以了,具体代码如下

相乘的代码:

/** * 两数相乘 * */Number.prototype.Multiply = function (right) {    let left = this;    //把左右两边的数转换成字符串    let leftString = left.toString();    let rightString = right.toString();    let leftHasDot = leftString.indexOf('.') > -1;    let rightHasDot = rightString.indexOf('.') > -1;    if (!leftHasDot && !rightHasDot) {        //如果为整数,则直接进行相乘        return left * right;    }    else {        //计算左右两边的小数位数        let leftDigit = leftHasDot ? leftString.split('.')[1].length : 0;        let rightDigit = rightHasDot ? rightString.split('.')[1].length : 0;        //计算相乘后的总小数位数        let digit = leftDigit + rightDigit;        let digitFlag = Math.pow(10, digit);        //左右两边的数转换成整数进行相乘,再除以总小数位数        let leftNumber = Number(leftString.replace('.', ''));        let rightNumber = Number(rightString.replace('.', ''));        return leftNumber * rightNumber / digitFlag;    }}

结果如下:

相除的代码:

/** * 两数相除 * */Number.prototype.Divide = function (right) {    let left = this;    //把左右两边的数转换成字符串    let leftString = left.toString();    let rightString = right.toString();    let leftHasDot = leftString.indexOf('.') > -1;    let rightHasDot = rightString.indexOf('.') > -1;    if (!leftHasDot && !rightHasDot) {        //如果为整数,则直接进行相乘        return left / right;    }    else {        //计算左右两边的小数位数        let leftDigit = leftHasDot ? leftString.split('.')[1].length : 0;        let rightDigit = rightHasDot ? rightString.split('.')[1].length : 0;        //计算相除后的总小数位数        let digit = rightDigit - leftDigit;        let digitFlag = Math.pow(10, digit);        //左右两边的数转换成整数进行相乘,再除以总小数位数        let leftNumber = Number(leftString.replace('.', ''));        let rightNumber = Number(rightString.replace('.', ''));        return (leftNumber / rightNumber).Multiply(digitFlag);    }}

结果如下:

相加的代码:

/** * 两数相加 * */Number.prototype.Add = function (right) {    let left = this;    //把左右两边的数转换成字符串    let leftString = left.toString();//把左边的数转换成字符串    let rightString = right.toString();//把右边的数转换成字符串    let leftHasDot = leftString.indexOf('.') > -1;    let rightHasDot = rightString.indexOf('.') > -1;    if (!leftHasDot && !rightHasDot) {        //如果为整数,则直接进行相加        return left + right;    }    else {        //计算左右两边的小数位数        let leftDigit = leftHasDot ? leftString.split('.')[1].length : 0;        let rightDigit = rightHasDot ? rightString.split('.')[1].length : 0;        //计算最大的小数位数        let maxDigit = Math.max(leftDigit, rightDigit);        let digitFlag = Math.pow(10, maxDigit);        //左右两边的数转换成整数进行相乘,再除以总小数位数        let leftNumber = left.Multiply(digitFlag);        let rightNumber = right.Multiply(digitFlag);        return (leftNumber + rightNumber) / digitFlag;    }}

结果如下图:

相减的代码

/** * 两数相减 * */Number.prototype.Subtract = function (right) {    let left = this;    let leftString = left.toString();//把左边的数转换成字符串    let rightString = right.toString();//把右边的数转换成字符串    let leftHasDot = leftString.indexOf('.') > -1;    let rightHasDot = rightString.indexOf('.') > -1;    if (leftString.indexOf('.') == -1 && rightString.indexOf('.') == -1) {        //如果为整数,则直接进行相减        return left - right;    }    else {        //计算最终小数位数        let leftDigit = leftHasDot ? leftString.split('.')[1].length : 0;        let rightDigit = rightHasDot ? rightString.split('.')[1].length : 0;        let maxDigit = Math.max(leftDigit, rightDigit);        let digitFlag = Math.pow(10, maxDigit);        //左右两边的数转换成整数进行相减,再除以总小数位数        let leftNumber = left.Multiply(digitFlag);        let rightNumber = right.Multiply(digitFlag);        return (leftNumber - rightNumber) / digitFlag;    }}

结果如下图:

标签: #js精度要求