简体   繁体   English

了解浮点问题

[英]Understanding floating point problems

Could someone here please help me understand how to determine when floating point limitations will cause errors in your calculations. 有人可以帮我理解如何确定浮点限制何时会导致计算错误。 For example the following code. 例如以下代码。

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

I have been unable to input any two values that have caused for me an incorrect result for this method. 我无法输入任何导致我这个方法的结果不正确的值。 If I remove the toFixed(4) I can infact see where the calculations start to lose accuracy (somewhere around the 6th decimal place). 如果我删除toFixed(4),我可以看到计算开始失去准确性的位置(大约在小数点后6位)。 Having said that though, my understanding of floats is that even small numbers can sometimes fail to be represented or have I misunderstood and can 4 decimal places (for example) always be represented accurately. 尽管如此,我对浮点数的理解是,即使是小数字有时也无法表示或者我误解了,并且可以精确地表示4位小数(例如)。

MSDN explains floats as such ... MSDN解释浮动本身 ......

This means they cannot hold an exact representation of any quantity that is not a binary fraction (of the form k / (2 ^ n) where k and n are integers) 这意味着它们不能保存任何不是二进制分数的数量的精确表示(形式为k /(2 ^ n),其中k和n是整数)

Now I assume this applies to all floats (inlcuding those used in javascript). 现在我假设这适用于所有浮点数(包括javascript中使用的浮点数)。

Fundamentally my question boils down to this. 从根本上说,我的问题归结为这一点。 How can one determine if any specific method will be vulnerable to errors in floating point operations, at what precision will those errors materialize and what inputs will be required to produce those errors? 如何确定任何特定方法是否容易受到浮点运算中的错误的影响,这些错误将以何种精度实现,以及产生这些错误需要哪些输入?

Hopefully what I am asking makes sense. 希望我所要求的是有道理的。

Start by reading What Every Computer Scientist Should Know About Floating Point : http://docs.sun.com/source/806-3568/ncg_goldberg.html 首先阅读每个计算机科学家应该知道的浮点数http//docs.sun.com/source/806-3568/ncg_goldberg.html

Short answer: double precision floats (which are the default in JavaScript) have about 16 decimal digits of precision. 简短回答:双精度浮点数(这是JavaScript中的默认值)具有大约16个十进制数字的精度。 Rounding can vary from platform to platform. 舍入可能因平台而异。 If it is absolutely essential that you get the consistently right answer, you should do rational arithmetic yourself (this doesn't need to be hard - for currency, maybe you can just multiply by 100 to store the number of cents as an integer). 如果你得到始终正确的答案绝对必要,你应该自己做理性算术(这不需要很难 - 对于货币,也许你可以乘以100来存储整数的分数)。

But if it suffices to get the answer with a high degree of precision, floats should be good enough, especially double precision. 但是如果能够以高精度得到答案就足够了,漂浮物应该足够好,特别是双精度。

There are two important thing you should now when dealing with floats: 在处理浮动时,你应该有两个重要的事情:

1- You should be aware of machine epsilon . 1-你应该知道机器epsilon To know how much precision you have. 要知道你有多精确。

2- You should not assume if two values are equal in base 10, they are equal in base 2 in a machine with precision limit . 2-您不应该假设两个值在基数10中相等,它们在具有精度限制的机器中的基数2中相等

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

Number 2 may be convincing enough to make you avoid comparing floating point numbers for equality, instead a threshold and greater-than or less-than operators can be used for comparison 数字2可能足够令人信服,可以避免比较浮点数的相等性,而是可以使用阈值和大于或小于运算符进行比较

The other answers have pointed to good resources to understanding this problem. 其他答案指出了理解这个问题的良好资源。 If your actually using monetary values in your code (as in your example) you should prefer Decimal types (System.Decimal in .Net). 如果您在代码中实际使用货币值(如您的示例中所示),则应该更喜欢Decimal类型(.Net中的System.Decimal)。 These will avoid some of the rounding problems from using floats and better match the domain. 这些将避免使用浮点数和更好地匹配域的一些舍入问题。

No, the number of decimal places has nothing to do with what can be represented. 不,小数位数与可以表示的内容无关。

Try .1 * 3, or 162.295 / 10, or 24.0 + 47.98. 尝试.1 * 3,或162.295 / 10,或24.0 + 47.98。 Those fail for me in JS. 那些在JS中失败了。 But, 24.0 * 47.98 does not fail. 但是,24.0 * 47.98不会失败。

So to answer your three questions, any operation for any precision is potentially vulnerable. 因此,要回答您的三个问题,任何精度的任何操作都可能存在漏洞。 Whether a given input will or won't is a question I don't know how to answer, but I have a hunch there are a number of factors. 一个给定的输入是否会是一个我不知道如何回答的问题,但我有预感有很多因素。 1) How close the actual answer is to the nearest binary fraction. 1)实际答案与最近的二进制分数有多接近。 2) The precision in the engine performing the calculation. 2)执行计算的发动机的精度。 3) The method used to perform the calculation (eg, multiplying by bit-shifting may give different results than multiplying by repeated addition) 3)用于执行计算的方法(例如,乘以比特移位可能得到与乘以重复加法不同的结果)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM