了解浮点问题

可能有人在这里请帮助我了解如何确定何时浮点限制会导致您的计算错误。 例如下面的代码。

CalculateTotalTax = function (TaxRate, TaxFreePrice) { return ((parseFloat(TaxFreePrice) / 100) * parseFloat(TaxRate)).toFixed(4); }; 

我一直无法input任何两个值,导致这种方法的结果不正确。 如果我删除toFixed(4),我可以看到计算开始失去准确性的地方(小数点后6位)。 尽pipe如此,我对浮点数的理解是,即使是很小的数字有时候也不能被表示,或者我误解了,并且可以精确地表示4位小数(例如)。

MSDN解释浮动这样 …

这意味着它们不能持有任何不是二元分数的数量(forms为k /(2 ^ n),其中k和n是整数)

现在我假设这适用于所有的浮动(包括在JavaScript中使用的那些)。

从根本上讲,我的问题归结为这一点。 如何确定是否有任何特定的方法容易出现浮点操作中的错误,这些错误将以何种精度实现以及需要哪些input来产生这些错误?

希望我所问的是有道理的。

首先阅读每位计算机科学家应该了解的浮点数 : http : //docs.sun.com/source/806-3568/ncg_goldberg.html

简短的回答:双精度浮点数(这是JavaScript中的默认值)具有大约16位十进制数字的精度。 舍入可以因平台而异。 如果你得到始终如一的正确答案是绝对必要的,那么你应该自己做一个合理的算术(对于货币来说,这不需要很难),也许你可以乘以100来存储整数的分数。

但是,如果足够高的精度得到答案,花车应该足够好,特别是双精度。

现在有两件重要的事情要处理浮动:

1-您应该知道机器epsilon 。 要知道你有多精确。

2-你不应该假设, 如果基数10中的两个值相等,在具有精度限制的机器中它们在基数2中是相等的 。

 if ((6.0 / 10.0) / 3.0 != .2) { cout << "gotcha" << endl; } 

数字2可能足以令人信服,使您避免比较浮点数的平等,而不是阈值和大于或小于运营商可用于比较

其他答案指出了解这个问题的好资源。 如果你的代码中实际使用的是货币值(比如你的例子),你应该更喜欢十进制types(System.Decimal in .Net)。 这些将避免使用浮点数的一些舍入问题,并更好地匹配域。

不,小数位数与可表示的内容无关。

尝试.1 * 3或162.295 / 10或24.0 + 47.98。 那些在JS中失败了。 但是,24.0 * 47.98不会失败。

所以要回答你的三个问题,任何精确的操作都可能是脆弱的。 一个给定的input是否会是一个问题,我不知道如何回答,但我有一个预感有很多因素。 1)实际答案与最近的二元分数有多接近。 2)发动机执行计算的精度。 3)用于执行计算的方法(例如,通过比特移位相乘可以得到不同于通过重复加法相乘的结果)