Из-за ошибок округления числа с плавающей точкой не являются ассоциативными.(a + b) + c! = a + (b + c).
Результат каждой операции округляется, чтобы соответствовать ограничениям кодирования чисел с плавающей запятой, и (a + b) + c реализуется как round (round (a + b)) + c) пока a + (b + c) как раунд (a + round (b + c)).
В качестве очевидной иллюстрации рассмотрим операцию (2 ^ -100 + 1 -1).Если интерпретировать как (2 ^ -100 + 1) -1, он вернет 0, так как 1 + 2 ^ -100 потребует слишком большой точности для чисел с плавающей запятой или двойного кодирования в IEEE754 и может быть закодирован только как 1.0.Хотя (2 ^ -100 + (1-1)) правильно возвращает 2 ^ -100, который может быть закодирован как с плавающей запятой, так и с удвоением.
Это тривиальный пример, но эти ошибки округления могут существовать после каждой операции и объяснять, почемуОперации с плавающей запятой не ассоциативны.
Базы данных, как правило, не возвращают данные в гарантированном порядке, и в зависимости от фактического заказа операции будут выполняться по-разному, что объясняет ваше поведение.
В целом по этой причинеЭто не очень хорошая идея, чтобы сделать сравнение равенства на поплавках.Обычно рекомендуется заменить a == b на abs (ab) "достаточно" мало.
"достаточно" может зависеть от вашего алгоритма.float эквивалентен ~ 6-7 десятичным знакам и удваивается до 15-16 десятичных знаков (и я думаю, что это то, что используется в вашей БД).В зависимости от количества вычислений могут быть затронуты последние 1–3 десятичных знака.
Лучше всего использовать
abs (ab)