什么是JavaScript无法准确表示的第一个数字?

时间:2014-04-03 09:52:21

标签: javascript

我正在使用货币值,因此准确计算非常重要。

我当前的代码将字符串分解为标记然后评估它们。对于十进制值,它首先将它们转换为整数,然后计算转换回小数。

例如,如果我有表达式

"0.1 * 0.2"

第一步是将其分解为代币0.1*0.2。然后它会做一些其他malarky和它需要多个0.10.2的数字。计算将是

1 * 2 / 100

计算以整数形式进行,以防止JavaScript舍入错误,即

0.1 * 0.2 == 0.020000000000000004

我的大学论点是,通过从字符串转换为浮点数,您最初已经失去了精确度。所以我的问题是什么是0的上限和下限,其中一个数字不能完全由JavaScript表示?所以我可以检查这个并处理它,如果那样&# 39;是正确的方法。

4 个答案:

答案 0 :(得分:3)

您描述的问题不是边界问题。 IEEE-754双精度二进制浮点数可以完美地表示值0.5,但不能完全代表0.1。请注意,那些具有相同的位数。问题不在于精确位置的数量,而是数字类型使用的数字基数与我们不同。它使用基数2,而不是基数10。

正如我们无法在基本10系统中准确表示1 / 3一样,某些数字无法在IEEE-754的基础2系统中准确表示。

2008年,IEEE推出了一项修订版,为IEEE-754添加了 new 格式(它定义了几种格式; JS使用的“双精度二进制”格式只是其中之一)称为“decimal64”,它使用基数10而不是基数2,用于需要以与我们相同的方式处理舍入的应用程序(财务应用程序等)。这可能会开始渗透到编程语言等等;目前,IEEE-754单精度和双精度是常用的,有些则不是基于最近的IEEE-754标准,如C#的decimal

与此同时,JavaScript中有“大十进制”库,例如big.js(尚未使用它,没有联属关系)。如果您搜索“JavaScript中的bignumber”或“JavaScript精确浮点”,您应该找到多个选项。

答案 1 :(得分:1)

我不认为有任何这样的数字可以说它是JavaScript无法准确表示的第一个数字。这完全是关于十进制数和精度损失。

另外,在JavaScript中没有十进制数据类型 - 唯一的数值数据类型是浮点数。 JavaScript使用64位浮点表示。

浮点舍入错误。由于缺少素数因子5,0.1在base-2中不能像在base-10中那样准确表示。还要注意每个浮点数都是这样的,并且基于IEEE 754 standard.

答案 2 :(得分:1)

如果我没弄错的话,所有JS引擎都使用IEEE 754 double来处理浮点数。

查看http://en.wikipedia.org/wiki/Double-precision_floating-point_format页面的“双精度示例”部分。在数字接近0的情况下,仔细查看subnormals公式:

$$(-1)^{\text{sign}} \times 2^{1 - \text{exponent bias}} \times 0.\text{mantissa}$$

因此,最接近零的数字,可用JavaScript浮点数据类型表示为2 1-1023 * 2 -52 = 2 -1022 * 2 -52 = 2 -1074

根据经验:

Math.pow(2,-1074) = 5e-324
Math.pow(2,-1075) = 0

答案 3 :(得分:0)

我注意到你正在进行货币计算。你可能会发现在这里使用整数更好。使用整数表示以美分为单位的价格。这消除了浮点问题,这些问题更适合于科学计算。这基本上相当于在java中使用BigDecimal。