Раунд PostgreSQL (v числовой, s int)

Какой метод делает Postgres round(v numeric, s int) использовать?

  1. Круглая половина
  2. Круглая половина вниз
  3. Круглая половина от нуля
  4. Округлить половину до нуля
  5. Вокруг половины до четного
  6. Вокруг половины до нечетного

Я ищу ссылку на документацию.

2 ответа

Решение

Извините, я не вижу никаких намеков на это в документации, но просмотр кода показывает, что он использует круглую половину от нуля; carry всегда добавляется к digitsтем самым увеличивая абсолютное значение переменной, независимо от того, что ее sign является. Простой эксперимент (psql 9.1) подтверждает это:

test=# CREATE TABLE nvals (v numeric(5,2));
CREATE TABLE
test=# INSERT INTO nvals (v) VALUES (-0.25), (-0.15), (-0.05), (0.05), (0.15), (0.25);
INSERT 0 6
test=# SELECT v, round(v, 1) FROM nvals;
   v   | round 
-------+-------
 -0.25 |  -0.3
 -0.15 |  -0.2
 -0.05 |  -0.1
  0.05 |   0.1
  0.15 |   0.2
  0.25 |   0.3
(6 rows)

Интересно, потому что round(v dp) использует половину даже:

test=# create table vals (v double precision);
CREATE TABLE
test=# insert into vals (v) VALUES (-2.5), (-1.5), (-0.5), (0.5), (1.5), (2.5);
INSERT 0 6
test=# select v, round(v) from vals;
  v   | round 
------+-------
 -2.5 |    -2
 -1.5 |    -2
 -0.5 |    -0
  0.5 |     0
  1.5 |     2
  2.5 |     2
(6 rows)

Последнее поведение почти наверняка зависит от платформы, поскольку похоже, что он использует rint(3) под капотом.

При необходимости вы всегда можете реализовать другую схему округления. См . Ответ Tometzky для примеров.

Это не задокументировано, поэтому может измениться.

Вот мои round_half_even(numeric,integer):

create or replace function round_half_even(val numeric, prec integer)
    returns numeric
as $$
declare
    retval numeric;
    difference numeric;
    even boolean;
begin
    retval := round(val,prec);
    difference := retval-val;
    if abs(difference)*(10::numeric^prec) = 0.5::numeric then
        even := (retval * (10::numeric^prec)) % 2::numeric = 0::numeric;
        if not even then
            retval := round(val-difference,prec);
        end if;
    end if;
    return retval;
end;
$$ language plpgsql immutable strict;

А также round_half_odd(numeric,integer):

create or replace function round_half_odd(val numeric, prec integer)
    returns numeric
as $$
declare
    retval numeric;
    difference numeric;
    even boolean;
begin
    retval := round(val,prec);
    difference := retval-val;
    if abs(difference)*(10::numeric^prec) = 0.5::numeric then
        even := (retval * (10::numeric^prec)) % 2::numeric = 0::numeric;
        if even then
            retval := round(val-difference,prec);
        end if;
    end if;
    return retval;
end;
$$ language plpgsql immutable strict;

Они обрабатывают около 500000 вызовов в секунду, в 6 раз медленнее, чем стандартные round(numeric,integer), Они также работают для нуля и для отрицательной точности.

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