FED实验室 - 专注WEB端开发和用户体验

Javascript 十进制数运算不精确问题

点滴Javascript 煦涵 5128℃ 0评论

对于一个新的Javascript开发者,可能很少注意到十进制数运算的不精确问题,我们先来看几个例子:

//eg: 1
var a = 0.1,
    b = 0.2,
    c = a + b;

//Outputs: 0.30000000000000004
console.log(c);

//eg: 2
var a = 600.90,
    b = 200.30,
    c = b * 3,
    d = a >= c;

//Outputs: false
console.log(d);

//Outputs: 600.9000000000001 
console.log(c);

从上例可以看出,十进制数的计算是非精确的。为什么会出现此种问题,请思考。本文的主要内容就是探讨出现此种现象的原因,以及更好的避免此种现象。

在JavaScript中所有的数字是IEEE 754浮点数。由于其编码的二进制性质,一些十进制数不能表示完全准确。这很是类似怎样的分数三分之一不能准确地表示与用有限位数的十进制数。一旦你打你的存储的极限,你需要准备转过最后一个数字向上或向下。

注:如果想详细了解IEEE754标准的,可以看看计算机组成原理

你首先想到的可能是尝试四舍五入至小数点第二位。不幸的是,JavaScript的内置round()函数只能四舍五入到最接近的整数。

//Outputs: 601
console.log(Math.round(c));

你的第二个想法可能像下面这样做:

//NumberObject.toFixed(num)
//num必需。规定小数的位数,是 0 ~ 20 之间的值,包括0 和20,有些实现可以支持更大的数值范围。如果省略了该参数,将用 0 代替。
//num超出范围报错“Uncaught RangeError: toFixed() digits argument must be between 0 and 20 ”

//Outputs: true
console.log(a.toFixed(2) >= c.toFixed(2));

虽然这样可以得到我们想要返回的结果,但是使用toFixed()方法,只是比较格式化后的值,而不是真正的值。那么我们如何来比较真正的精确的只呢?

幸运的是,我们有一个容易的方式把这些小数转换为整数。

var a = 60090,
    b = 20030,
    c = b * 3,
    d = a >= c;

//Outputs: true
console.log(d);

//Outputs: 60090
console.log(c);

因为在Javascript中整数可以完全准确地表示,这样我们就可以避开浮点数运算产生的问题。

当然,这并不能解决所有的问题。整数和小数的乘除元素可能仍然会导致不精确的值,但整数加法,减法和乘法运算将是准确的。

感谢您的阅读,希望文中内容对您有帮助,文中不足之处,还望批评斧正。

下面是「FED实验室」的微信公众号二维码,欢迎扫描关注:

FED实验室

行文不易,如有帮助,欢迎打赏!

赞赏支持or喜欢 (0)or分享 (0)
捐赠共勉
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽