Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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). 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.

MSDN explains floats as such...

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)

Now I assume this applies to all floats (inlcuding those used in 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.

like image 306
Maxim Gershkovich Avatar asked Jan 12 '11 01:01

Maxim Gershkovich


2 Answers

Start by reading What Every Computer Scientist Should Know About Floating Point: 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. 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).

But if it suffices to get the answer with a high degree of precision, floats should be good enough, especially double precision.

like image 147
Raph Levien Avatar answered Oct 12 '22 01:10

Raph Levien


There are two important thing you should now when dealing with floats:

1- You should be aware of machine 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.

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

like image 43
Nylon Smile Avatar answered Oct 12 '22 02:10

Nylon Smile