PostgreSQL round(v numeric,s int)

Сух*_*й27 7 postgresql floating-point rounding

Postgres 使用哪种方法round(v numeric, s int)

  1. 圆的一半
  2. 圆半下来
  3. 离零的一半
  4. 圆半朝零
  5. 圆一半甚至
  6. 圆半到奇数

我正在寻找文档参考.

Tom*_*zky 7

它没有记录,所以它可以改变。

这是我的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;
Run Code Online (Sandbox Code Playgroud)

并且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;
Run Code Online (Sandbox Code Playgroud)

它们每秒管理大约 500000 次调用,比标准round(numeric,integer). 它们也适用于零精度和负精度。


Ary*_*rog 6

对不起,我在文档中没有看到任何暗示,但是看一下代码就表明它正在使用距离零的一半 ; 将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)
Run Code Online (Sandbox Code Playgroud)

有意思,因为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)
Run Code Online (Sandbox Code Playgroud)

后一种行为几乎肯定是依赖于平台的,因为它看起来像是在引擎盖下使用rint(3).

如有必要,您可以随时实施不同的舍入方案.有关示例,请参阅Tometzky的答案.