Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

postgresql round half down function

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
like image 578
BangTheBank Avatar asked Sep 21 '12 08:09

BangTheBank


People also ask

How do I round down in PostgreSQL?

In PostgreSQL, the floor() function is used for rounding a number down to the nearest integer. It's basically the opposite of ceiling() , which rounds a number up. It's also similar to round() , except that it only rounds down. The round() function will round up or down as required.

How do I round to 2 decimal places in PostgreSQL?

select ROUND(12.924, 2); We have provided “2” in the query. For this purpose, we need to input the value for 3 decimal places. i.e., “12.924” so that it can jump to 2 decimal places.

How do I cast an expression in PostgreSQL?

CAST ( expression AS target_type ); where: The expression can be a constant or a table column or any expression that finally resolves to a value, The target_type is the final datatype to which you want to convert the above expression to.

What is the data type for decimal in PostgreSQL?

NUMERIC. The DECIMAL and NUMERIC data types are equivalent in PostgreSQL. Both of them have a variable storage size, i.e. the storage size depends on the number of digits contained.


1 Answers

A method is very quick without creating a new FUNCTION which can round half down as below:

-- Round half up

round($n, 3)

-- Round half down

round($n-0.5, 3)
like image 165
congtinit Avatar answered Sep 28 '22 16:09

congtinit