Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase transaction precision loss

In Firebase real time database i have a path like this ../funds/balance with a value of 10.

I have a function doing a transaction which decrease the balance by 2 cents.

The first time i remove 2 cents everything works and balance is saved has 9.98.

I do it one more time everything console log show i read 9.98 from the db and after data is updated firebase console show 9.96.

Next time i do it remember that Firebase console shows 9.96 but when i console log the value received in the transaction is currently 9.96000001.

Someone nows why.

like image 493
Simon Cadieux Avatar asked Mar 06 '26 22:03

Simon Cadieux


1 Answers

This is a well-known property of floating-point representations.

The issue arises because, in this case, because 0.02 cannot be represented exactly as a floating-point number. It can be represented exactly in decimal (2x10^-1), but in binary it has a recurring "1001" (1.1001100110011001... x2^-3).

What you are seeing is analogous to representing 1/3 in decimal as 0.333. You expect that subtracting 1/3 from one 3 times would leave 0, but subtracting 0.333 from one 3 times leaves 0.001.

The solution is not to represent money as floating-point. In SQL you'd use a MONEY, NUMERIC or DECIMAL type or, more generally, you can represent money as an integer number of pennies (or hundreths of a penny, etc., according to your needs).

There's an article called "What Every Computer Scientist Should Know About Floating-Point Arithmetic" that you can find online that explains the issue.

like image 67
Emmet Avatar answered Mar 10 '26 11:03

Emmet