Вычисления с плавающей точкой довольно забавная вещь: Попробуйте это:
SELECT FLOOR(38774/184*126*23+0.5);
SELECT FLOOR(38774*126*23/184+0.5);
SELECT FLOOR(ROUND(38774/184*126*23+0.5, 3));
Что тут происходит?
Наиболее важной частью является то, что 38774/184
не имеет точного представления в виде числа с плавающей запятой - вы всегда и немного меньше. С остальными вычислениями, составляющими ровно 610691, вы в итоге чуть-чуть не дотянете до 610691, что приведет FLOOR
610690.
Вторая строка избегает этого, перегруппировывая части вычисления в последовательность, которая имеет точное представление в виде числа с плавающей запятой.
Третья строка использует ROUND
отрезать очень маленькую разницу, тем самым делая FLOOR
работать как положено.
Практическое правило. Числа с плавающей точкой не дают точных результатов. Хотя они чаще всего являются «достаточно точными», существуют крайние случаи, когда это не так. Вы просто нажали один, и довольно обычный: преобразование обратно в целое число через FLOOR
или же CEIL
,
Теперь, чтобы ответить на ваш вопрос: из опыта я бы приказал вычислить так, как это делает 2-я строка - большие числа (в диапазоне INT32) с большей вероятностью приведут к правильному FLOOR
, Если вычислительная стоимость приемлема для вас, я бы пошел на
SELECT FLOOR(ROUND(38774*126*23/184+0.5, 3));
и будьте вполне уверены, что все крайние случаи покрыты.
ROUND
повлиять на это? Мой подход был похожFLOOR(x*100+0.5)/100
, Так что в вашем примере сROUND
следующее округлено «неправильно»:FLOOR(ROUND(4.994999999*100+0.5,3))/100=5.00
вместо4.99