我正在使用货币值,因此准确计算非常重要。
我当前的代码将字符串分解为标记然后评估它们。对于十进制值,它首先将它们转换为整数,然后计算转换回小数。
例如,如果我有表达式
"0.1 * 0.2"
第一步是将其分解为代币0.1
,*
和0.2
。然后它会做一些其他malarky和它需要多个0.1
和0.2
的数字。计算将是
1 * 2 / 100
计算以整数形式进行,以防止JavaScript舍入错误,即
0.1 * 0.2 == 0.020000000000000004
我的大学论点是,通过从字符串转换为浮点数,您最初已经失去了精确度。所以我的问题是什么是0的上限和下限,其中一个数字不能完全由JavaScript表示?所以我可以检查这个并处理它,如果那样&# 39;是正确的方法。
答案 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公式:
因此,最接近零的数字,可用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。