How to avoid floating point errors?

I tried to write a function to approximate the square roots (I know that there is a mathematical module ... I want to do it myself), and I was screwed up with floating point arithmetic. How can you avoid this?

def sqrt(num): root = 0.0 while root * root < num: root += 0.01 return root 

Using this, we obtain the following results:

 >>> sqrt(4) 2.0000000000000013 >>> sqrt(9) 3.00999999999998 

I understand that I can just use round() , but I want to make this very accurate. I want to be able to calculate up to 6 or 7 digits. This is not possible if I round out. I want to understand how to handle floating point calculations in Python correctly.

+10
python floating-point floating-point-precision
source share
1 answer

This has nothing to do with Python - you will see the same behavior in any language using your hardware binary floating point arithmetic. Read the docs first.

After you read this, you will realize that you are not adding one hundredths to your code. This is exactly what you add:

 >>> from decimal import Decimal >>> Decimal(.01) Decimal('0.01000000000000000020816681711721685132943093776702880859375') 

This line shows the exact decimal value of the binary floating ("double precision" in C) approximation to the exact decimal value of 0.01. What you really add is a little more than 1/100.

Floating point numerical error management is a field called numerical analysis and is a very large and complex topic. As long as you are frightened by the fact that floats just come close to decimal values, use the decimal module. This will remove the world of "minor problems" for you. For example, given this small modification to your function:

 from decimal import Decimal as D def sqrt(num): root = D(0) while root * root < num: root += D("0.01") return root 

then

 >>> sqrt(4) Decimal('2.00') >>> sqrt(9) Decimal('3.00') 

This is not entirely accurate, but may be less unexpected in simple examples, because now it adds exactly one hundredth. A.

An alternative is to stick with a float and add something exactly represented as a binary float: values โ€‹โ€‹of the form I/2**J For example, instead of adding 0.01, add 0.125 (1/8) or 0.0625 (1/16).

Then find the โ€œNewton methodโ€ to calculate the square roots; -)

+15
source share

All Articles