the round(numeric,integer) function in PostgreSQL only rounds up:
round(cast (41.0255 as numeric),3) ==> 41.026
Since we need a round function which returns 41.025 and (quite surprisingly) there isn't such a function in PostgreSQL (we're using 9.1.5), we wrote a "wrapper" function which in the very first version is quite naive and rough...but we didn't find anything better due the lack of native support for this kind of problems in plpgsql.
The code is showed below. The problem is that it's too slow for our purposes. Could you suggest a better way to deal with this task?
Here's the code:
CREATE OR REPLACE FUNCTION round_half_down(numeric,integer) RETURNS numeric
AS $$
DECLARE
arg ALIAS FOR $1;
rnd ALIAS FOR $2;
tmp1 numeric;
res numeric;
BEGIN
tmp1:=arg;
IF cast(tmp1 as varchar) ~ '5$' THEN res:=trunc(arg,rnd);
ELSE res:=round(arg,rnd);
END IF;
RETURN res;
END;
$$ LANGUAGE plpgsql;
I need to cast the numeric value and use regexp...that's what (I suppose) kills performances.
Just so you know: we need this because we have to compare numbers that were stored in two different columns (on two different tables) but with different numeric data type: one is double and one is real. The problem is that when inserting into a real data type column, PostgreSQL performs ROUND HALF DOWN while it doesn't provide such option via its mathematical functions!
EDIT:
The function is actually bugged. Was a first quick rewriting as an attempt to improve performances of a working function but very slow.
Behavior must match the following:
IF
the decimal digit being put off from rounding is <=5 => trunc
ELSE
round up.
Some examples:
select round_half_down(cast (41.002555 as numeric),3) -- 41.002
select round_half_down(cast (41.002555 as numeric),4) -- 41.0025
select round_half_down(cast (41.002555 as numeric),5) -- 41.00255
while the round function in PostgreSQL gives:
select round(cast (41.002555 as numeric),3) -- 41.003
-41.0255
rounded to-41.025
or-41.026
? Also: Would you want41.02551
rounded to41.025
or41.026
? – Moller