Потеря точности транзакции Firebase

В базе данных реального времени Firebase у меня есть такой путь ../funds/balance со значением 10.

У меня есть функция, выполняющая транзакцию, которая уменьшает баланс на 2 цента.

В первый раз, когда я удаляю 2 цента, все работает, а баланс сохраняется - 9,98.

Я делаю это еще раз, когда все, что отображается в журнале консоли, я читал из базы данных 9.98, а после обновления данных консоль firebase показывает 9.96.

В следующий раз, когда я сделаю это, я помню, что консоль Firebase показывает 9.96, но когда я веду консольный журнал, значение, полученное в транзакции, в настоящее время составляет 9.96000001.

Кто-то теперь понимает, почему.

Интеграция Angular - Firebase Analytics
Интеграция Angular - Firebase Analytics
Узнайте, как настроить Firebase Analytics и отслеживать поведение пользователей в вашем приложении Angular.
3
0
293
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это хорошо известное свойство представлений с плавающей запятой.

Проблема возникает из-за того, что в данном случае 0,02 не может быть точно представлено как число с плавающей запятой. Он может быть представлен точно в десятичный (2x10 ^ -1), но в двоичный он имеет повторяющееся «1001» (1.1001100110011001 ... x2 ^ -3).

То, что вы видите, аналогично представлению 1/3 в десятичной дроби как 0,333. Вы ожидаете, что вычитание 1/3 из единицы 3 раза оставит 0, но вычитание 0,333 из единицы 3 раза оставит 0,001.

Решение состоит не в том, чтобы представлять деньги как числа с плавающей запятой. В SQL вы должны использовать тип MONEY, NUMERIC или DECIMAL или, в более общем смысле, вы можете представить деньги в виде целого числа пенни (или сотых долей пенни и т. д., В зависимости от ваших потребностей).

В Интернете есть статья под названием "Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой", в которой объясняется проблема.

Да, я знаю, но консоль Firebase показывает, что она хранит 9.96, тогда она должна показать 9.960000000001. не 9.96.

Simon Cadieux 12.10.2018 18:48

Хорошо, спасибо, я понял, на самом деле я прочитал кое-что, что не было полностью точным о том, как лучше всего обрабатывать валюту, и, поскольку мне не нужно было иметь дело с этой стороной javascript, я не думал, что это 9,96 * 100 это давало 9.96000000001 что-то вроде этого. Значение, полученное из БД, действительно было в порядке, оно было 9,96.

Simon Cadieux 12.10.2018 19:32

Другие вопросы по теме