JS中乘除法运算问题
发布于 5 年前 作者 dingyuanwu 6049 次浏览 来自 问答

屏幕快照 2019-09-05 上午11.05.30.png 这种现象是怎样出现的? 在涉及金钱的计算时,这个问题很致命

17 回复

IEEE 754. 楼主没用过其它开发语言么

原因我知道,只是在js下,9.9 * 100 的结果是990,大部分类似的计算结果都是对的,但是上面的几个是在js下是例外,关键是还不知道怎样处理,有多一点的,也有少了一点的,有统一的处理方式吗?

@dingyuanwu 所有语言都是一样的。要么就用处理浮点数的专用方法/包。 js 可以考虑这个 https://github.com/josdejong/mathjs 或者在数据库进行处理。

TIM图片20190906091850.png 请你们再也不要攻击js计算不准确了,哎,又给你们普及知识了。惭愧!

js采用的是双精度浮点数,对于浮点数的计算,结果就是这样子呀

精度问题就从精度角度解决,比如你要求小数点后两位,每次计算完后将数据处理成小数点后两位就行

但是JS自己实际是做了一些处理的,上面给的例子就是 有的结果和预期的一致,有的不一致 没有办法,我们只能自己解决了 但是还是想知道这种部分对,部分错的现象是怎样产生的 在C、C++或者Java中,精度缺失是都会缺失,但是JS做了部分处理,导致了下面的情况: 屏幕快照 2019-09-05 下午3.00.19.png

众所周知,精度问题无论哪个语言都需要 Decimal 去处理的,float 精度有问题,Decimal 处理方式是按字符串处理,可以保证绝对的精度。

bignumber.js 使用这个库可以处理精度问题

@Sirormy Decimal 照样有 入参或者数据库取数 稍微有问题 就呵呵 银行利息啊

@dingyuanwu 测试一下toFixed

// toFixed兼容方法 Number.prototype.toFixed = function (n) { if (n > 20 || n < 0) { throw new RangeError(‘toFixed() digits argument must be between 0 and 20’); } const number = this; if (isNaN(number) || number >= Math.pow(10, 21)) { return number.toString(); } if (typeof (n) == ‘undefined’ || n == 0) { return (Math.round(number)).toString(); }

let result = number.toString();
const arr = result.split('.');

// 整数的情况
if (arr.length < 2) {
    result += '.';
    for (let i = 0; i < n; i += 1) {
        result += '0';
    }
    return result;
}

const integer = arr[0];
const decimal = arr[1];
if (decimal.length == n) {
    return result;
}
if (decimal.length < n) {
    for (let i = 0; i < n - decimal.length; i += 1) {
        result += '0';
    }
    return result;
}
result = integer + '.' + decimal.substr(0, n);
const last = decimal.substr(n, 1);

// 四舍五入,转换为整数再处理,避免浮点数精度的损失
if (parseInt(last, 10) >= 5) {
    const x = Math.pow(10, n);
    result = (Math.round((parseFloat(result) * x)) + 1) / x;
    result = result.toFixed(n);
}

return result;

};

看来是得自己处理一下,不完后续可能会有问题

Number.prototype.toPrecision

@nwljy 银行别用 nodejs

@Sirormy 精度问题和 nodejs 有啥关系? 难道 js 没有处理 numberic 的库,或者不能在数据库计算结果? 难道 java 就没这问题?

回到顶部