有人可以帮助我了解如何确定浮点限制何时会导致计算错误。例如以下代码。
CalculateTotalTax = function (TaxRate, TaxFreePrice) {
return ((parseFloat(TaxFreePrice) / 100) * parseFloat(TaxRate)).toFixed(4);
};
我无法输入任何导致此方法错误结果的值。如果我删除toFixed(4),我可以看到计算开始失去准确性的位置(大约在小数点后6位)。尽管如此,我对浮点数的理解是,即使是小数字有时也无法表示或者我误解了,并且可以精确地表示4位小数(例如)。
MSDN将浮动解释为such ...
这意味着他们无法保持准确 表示任何数量 不是二进制分数(形式为k / (2 ^ n)其中k和n是整数)
现在我假设这适用于所有浮点数(包括javascript中使用的浮点数)。
从根本上说,我的问题归结为此。如何确定任何特定方法是否容易受到浮点运算中的错误的影响,这些错误将以何种精度实现,以及产生这些错误需要哪些输入?
希望我所要求的是有道理的。
答案 0 :(得分:10)
首先阅读每个计算机科学家应该知道的浮点数: http://docs.sun.com/source/806-3568/ncg_goldberg.html
简答:双精度浮点数(这是JavaScript中的默认值)具有大约16位十进制数字的精度。舍入可能因平台而异。如果你得到始终正确的答案绝对必要,你应该自己做理性算术(这不需要很难 - 对于货币,也许你可以乘以100来存储整数的分数)。
但如果能够以高精度得到答案就足够了,漂浮物应该足够好,特别是双精度。
答案 1 :(得分:4)
在处理浮动时,你应该有两个重要的事情:
1-你应该知道machine epsilon。要知道你有多精确。
2-你不应该假设if two values are equal in base 10, they are equal in base 2 in a machine with precision limit。
if ((6.0 / 10.0) / 3.0 != .2) {
cout << "gotcha" << endl;
}
2号可能足够令人信服,可以避免比较浮点数的相等性,而是可以使用阈值和大于或小于运算符进行比较
答案 2 :(得分:2)
其他答案指出了理解这个问题的良好资源。如果您在代码中实际使用货币值(如您的示例中所示),则应该更喜欢Decimal类型(.Net中的System.Decimal)。这些将避免使用浮点数和更好地匹配域的一些舍入问题。
答案 3 :(得分:1)
不,小数位数与可以表示的内容无关。
尝试.1 * 3,或162.295 / 10,或24.0 + 47.98。那些在JS中失败了。但是,24.0 * 47.98不会失败。
因此,要回答您的三个问题,任何精确度的任何操作都可能存在漏洞。一个给定的输入是否会是一个我不知道如何回答的问题,但我有预感有很多因素。 1)实际答案与最近的二进制分数有多接近。 2)执行计算的发动机的精度。 3)用于执行计算的方法(例如,乘以位移可能会产生与乘以重复加法不同的结果)