如何在PostgreSQL中执行级联舍入



级联舍入是一种在保留浮点数组和的同时对其进行舍入的算法。如何在PostgreSQL中实现此算法?

您可以在plpgsql:中实现此函数

create or replace function cascade_rounding(float[])
returns int[] immutable language plpgsql as $$
declare
fp_total float = 0;
int_total int = 0;
fp_value float;
int_value int;
result int[];
begin
foreach fp_value in array $1 loop
int_value := round(fp_value + fp_total) - int_total;
fp_total := fp_total + fp_value;
int_total := int_total + int_value;
result := result || int_value;
end loop;
return result;
end $$;
select cascade_rounding(array[1.1, 1.2, 1.4, 1.2, 1.3, 1.4, 1.4])
cascade_rounding
------------------
{1,1,2,1,1,2,1}
(1 row) 

尝试Db<>中的函数不停摆弄

更新。您可以将函数应用于列。示例表:

create table my_table(id serial primary key, float_number float);
insert into my_table (float_number) 
select unnest(array[1.1, 1.2, 1.4, 1.2, 1.3, 1.4, 1.4])

查询:

select 
unnest(array_agg(id order by id)) as id,
unnest(array_agg(float_number order by id)) as float_number,
unnest(cascade_rounding(array_agg(float_number order by id))) as int_number
from my_table;

然而,这并不是一个完美的解决方案。该查询相当复杂且不理想。

在Postgres中,您可以创建一个自定义聚合,并将其用作窗口函数。这不是特别困难,但需要一些知识,请参阅文档中的用户定义聚合。

create type cr_type as (int_value int, fp_total float, int_total int);
create or replace function cr_state(state cr_type, fp_value float)
returns cr_type language plpgsql as $$
begin
state.int_value := round(fp_value + state.fp_total) - state.int_total;
state.fp_total := state.fp_total + fp_value;
state.int_total := state.int_total + state.int_value;
return state;
end $$;
create or replace function cr_final(state cr_type)
returns int language plpgsql as $$
declare
begin
return state.int_value;
end $$;
create aggregate cascade_rounding_window(float) (
sfunc = cr_state,
stype = cr_type,
finalfunc = cr_final,
initcond = '(0, 0, 0)'
);

将聚合用作窗口函数:

select 
id, 
float_number, 
cascade_rounding_window(float_number) over (order by id) as int_number
from my_table;
id | float_number | int_number
----+--------------+------------
1 |          1.1 |          1
2 |          1.2 |          1
3 |          1.4 |          2
4 |          1.2 |          1
5 |          1.3 |          1
6 |          1.4 |          2
7 |          1.4 |          1
(7 rows)    

Db<>不停摆弄

最新更新