Почему Oracle не использует правило банкиров (метод округления)?
Правило Oracle Bankers
Ответы (5)
Точная десятичная арифметика - большой и сложный предмет.
Google 'Майк Колишоу десятичное округление', если вы хотите прочитать кхм Оракул по этому вопросу.
В основном существует множество схем округления, которые возможны:
Округлите все в меньшую сторону - по умолчанию для большинства языков, включая C, поскольку Oracle написан на C, возможно, поэтому они так и делают.
Соберите все в кучу - редко встречается, но иногда необходимо реализовать из-за неясных рыночных и налоговых правил.
Базовое половинное округление — все, что выше 0,5, округляется в большую сторону, все остальное округляется в меньшую сторону.
Щедрое половинное округление — все, что меньше 0,5, округляется вниз, все остальное округляется вверх.
Округление банкиров — четные числа следуют основному правилу округления до половины, нечетные числа — правилу щедрого округления до половины. Это редко можно увидеть в реальных банках, которые предпочитают округлять деньги, если они приходят к ним, и округлять в меньшую сторону, когда они идут к клиентам.
ORACLE NUMBER на самом деле является довольно хорошей реализацией десятичной арифметики и точен, насколько это возможно.
Oracle реализовал половину округления от нуля:
SQL> select round(22.5) from dual
2 /
ROUND(22.5)
-----------
23
SQL> select round(23.5) from dual
2 /
ROUND(23.5)
-----------
24
SQL> select round(-23.5) from dual
2 /
ROUND(-23.5)
------------
-24
SQL> select round(-22.5) from dual
2 /
ROUND(-22.5)
------------
-23
SQL>
Почему бы им не изменить его на Банковское округление? Что ж, для большинства целей достаточно округлить половину от нуля. Кроме того, есть этот старый запасной вариант, его изменение, вероятно, нарушит слишком большую часть существующей кодовой базы - как собственной, так и всех их клиентов Oracle.
Тема старая, но может кому пригодится. Двоичные числа с плавающей запятой и двойные числа Oracle следуют правилу округления банкира при округлении до целого числа. Так что вы можете использовать это. Это уродливо, но это работает:
given : price = 2.445 SQL> select round(to_binary_float(price * 100)) / 100 as price_rounded from dual; price_rounded ------------- 2.44 given : price = 2.435 SQL> select round(to_binary_float(price * 100)) / 100 as price_rounded from dual; price_rounded ------------- 2.44
В этом примере необходимы умножение и деление на 100. Мне не удалось выяснить особенности поведения, но выбор round(to_binary_float(price), 2) для некоторого десятичного числа, цена, похоже, не всегда округляется вверх или вниз по одним и тем же правилам. Однако я обнаружил, что округление до целого числа постоянно дает мне то, что мне нужно.
Вы всегда можете реализовать собственную функцию округления банкира, как описано здесь.
Округление банкира от 0,5 до 0: оно округляется до четных чисел.