Posts

Floating point math is the devil!

avatar of @edicted
25
@edicted
·
·
0 views
·
3 min read

https://www.youtube.com/watch?v=0cVlTeIATBs

Programming exercise:

Head on over to https://playcode.io/new/

Type in:

console.log(0.1 * 125) 

No problem!

Look at you go, you're a programmer now!

Now add a zero!

Easy, add another 0.

What's the point of this again?

Pipe down: add two more zeros.

Okay, this is getting ridiculous.

Ah, so close, just two more zeros to go!

WHAT?!?!

GAH! WHY!?

How does 0.0000001 x 125 = 0.0000124999999999???

The math can't get more basic, why the rounding error?

Short answer: floating point math.

You and I are used to math being done in base 10.

  • There are ten digits.
  • 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
  • When multiplying or dividing by a power of 10, the decimal point moves.

Computers do math in base 2.

  • There are two digits
  • on/off true/false 1/0
  • When multiplying or dividing by a power of 2, the decimal point moves.

So when you get into fractions, a computer can't store numbers in base two like we think of numbers in base ten. For example, try to write 1/3 in base ten. What do you get?

0.333333333333333333333...

1/3 can not be expressed perfectly as a base 10 decimal. If you were using a base 3 number system 1/3 would be 0.1 and could be expressed perfectly without a rounding error. This same thing happens with floating point math to create some weird rounding errors (often times when multiplying/dividing numbers).

https://floating-point-gui.de/formats/binary/

Who cares?

I care! DAMMIT! When you're trying to keep track of money in a database (I am) then these rounding errors become unacceptable and totally ruin database integrity. In the case of the bug I just found, I wasn't even trying to keep track of money, but rather have been working on my sliding-scale voting system.

The schedule I've developed DEPENDS on the numbers being exact. If a variable in the database gets voted up/down and becomes 0.00014999999 instead of 0.00015 my code would get very confused and stop working.

This is exactly why every database has a DECIMAL class that completely avoids floating point math and actually uses base 10. It's slower and requires more storage but the loss in performance is more than worth it to maintain database integrity in many cases (especially those involving money).

In the case of my code, I was actually using a DECIMAL when the error occurred, but I was multiplying it by another exponent that was by default a floating point number. In the background it must have cast the entire result to a float and thus there was a bug in my code.

return cast(power(10, deviation) as decimal(65,30)) * temp; 

In order to fix the bug I had to CAST the exponent as a decimal in order to stop floating-point math from occurring. Problem solved.

Conclusion

Well, that's how my day is going.
Just grinding out more code.
It's been slow going but hopefully I can pick up the pace.

Market Watch Post Script:

Bitcoin shorts on Bitfinex are at local record highs.

Are the bears getting a bit too greedy? Will there be an epic short squeeze?
Or will this market cave in once again?
Time will tell.