Как я могу запретить облачным функциям Google генерировать небольшие смещения при вычитании числа? - PullRequest
0 голосов
/ 12 марта 2020

У меня действительно странное поведение с вычитанием чисел в Google Firestore с Google Cloud Functions.

Вот мой тестовый код Google Functions:

exports.testCounter = functions.https.onCall((data, context) => {
    db.collection('counter').doc('test').update({
        count: admin.firestore.FieldValue.increment(-0.0005)
    });
});

А потом я вызываю Функция из Cli:

firebase functions:shell
testCounter({test: "demo"})

Это документ, который я создал для тестирования: Исходная схема

Затем после первого выполнения все работает точно так, как ожидалось, и число 5 теперь 4.9995 .: Документ после первого выполнения

Однако после второго выполнения 4.9995 не соответствует 4.9990, как ожидалось, но изменяется на 4.9990000000000006 .: Документ после второго выполнения

У кого-нибудь есть идеи как это исправить? Или это как-то ожидаемое поведение?

Спасибо и хорошего дня!

Рик

Ответы [ 3 ]

2 голосов
/ 12 марта 2020

Это стандартное поведение для чисел с плавающей запятой, использующих стандарт IEEE 754 , который Firestore использует . Короче говоря, компьютеры теряют точность при эффективном хранении данных с плавающей запятой.

Если вы не можете принять это поведение, вам не следует хранить числа с плавающей запятой вообще, а вместо этого просто хранить целые числа. Целое число должно содержать всю требуемую точность, которая обычно требуется для эквивалента с плавающей запятой, за исключением того, что вы умножаете число с плавающей запятой на требуемую точность.

Например, если вам нужно три десятичных знака точности (например, 5,005 ), умножьте это число с плавающей точкой на 1000, отбросьте дробную часть и сохраните целое число 5005. Если вам нужно добавить .005, вместо этого вы должны добавить 5. Затем вы можете отформатировать это число любым способом на клиенте.

0 голосов
/ 12 марта 2020

Как объяснил Дуг, проблема связана с поведением чисел с плавающей запятой.

Одним из решений является использование в вашей облачной функции библиотеки big. js.

Хорошо работает в облачных функциях (как в любом коде Node.js), но это означает, что вы больше не сможете использовать admin.firestore.FieldValue.increment().

0 голосов
/ 12 марта 2020

На самом деле это не проблема Firebase, она присуща числам с плавающей запятой.

(4.9990000006).toFixed(4); // 4.9990

Замените параметр 4 в toFixed с любой точностью, которая вам нужна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...