Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore increment floating points issue

Note that I know there have been some other questions, but no real answer, on SO, regarding this issue.

So, what has been happening since the increment field value was implemented, is that when incrementing floating numbers, most of the time you'll get a dozen decimals instead of the actual number.

// incrementing 0, with 0.1, 11 times, returns 1.0999999999999999
Math.round( 1.0999999999999999 * 100 + Number.EPSILON ) / 100 

This returns the correct number ... so I wonder, can't this be implemented inside the method that deals with incrementing the actual value inside Firestore ?

Problem is, when I want to show numbers locale-based, I use the following:

number.toLocaleString( undefined, { minimumFractionDigits: 2 })

That would show 1.09 which is wrong, and customers get confused about their earnings.

What's to be done aside manipulating the data after receiving it client side?

Another side effect of this is that when using incrementing a big negative value, sometimes, for some reason, you get that +e inside your value in Firestore, and when fetching it server-side ( at least with the PHP Admin SDK ), the number ends up as a string, and not as an integer.

like image 803
Eduard Avatar asked Oct 22 '25 19:10

Eduard


1 Answers

According to the documentation, Cloud Firestore stores floating point numbers in IEEE 754 format. Please take some time to understand what this format implies. Basically, you can't count on floating point number to retain exactly the accuracy that you've specified, as the format can't possibly do that for some numbers. You can expect some small variation when the number is stored. A good summary of this type of behavior can already be found here on Stack Overflow:

  • Why are floating point numbers inaccurate?

If you must retain numerical accuracy, look into using a library that will help load and store numbers that have the accuracy you need. Pretty much all financial application will do something like this, as IEEE 754 can effectively lose data in order to compress the data down to a small size.

like image 50
Doug Stevenson Avatar answered Oct 25 '25 12:10

Doug Stevenson