您的解决方案适用于任何版本的 PostgreSQL,
SELECT round(1/3.::numeric,4);
但是“是否有直接舍入浮点数的函数?”的答案?, 是没有。
选角问题
您正在报告一个众所周知的“错误”,某些 PostgreSQL 函数中缺少重载...为什么(???):我认为“这是一个缺陷”(!),但是@CraigRinger,@Catcall(见 Craig's anser 的评论)和 PostgreSQL 团队同意“PostgreSQL 的历史理由”。
解决方案是开发一个集中且可重用的“片段库”,例如 pg_pubLib。它实现了下面描述的策略。
重载作为铸造策略
您可以使用以下方法重载内置 ROUND 函数,
CREATE FUNCTION ROUND(float,int) RETURNS NUMERIC AS $f$
SELECT ROUND($1::numeric,$2);
$f$ language SQL IMMUTABLE;
现在你的梦想将成为现实,试试吧
SELECT round(1/3.,4); -- 0.3333 numeric
它返回一个(十进制)NUMERIC 数据类型,这对于某些应用程序来说很好......另一种方法是使用round(1/3.,4)::float
或创建一个round_tofloat()
函数。
其他替代方法,为了保留输入数据类型并使用浮点数的所有精度范围(请参阅IanKenney 的答案),是在定义精度时返回浮点数,
CREATE or replace FUNCTION ROUND(
input float, -- the input number
accuracy float -- accuracy
) RETURNS float AS $f$
SELECT ROUND($1/accuracy)*accuracy
$f$ language SQL IMMUTABLE;
COMMENT ON FUNCTION ROUND(float,float) IS 'ROUND by accuracy.';
尝试
SELECT round(21.04, 0.05); -- 21.05
SELECT round(21.04, 5::float); -- 20
SELECT round(pi(), 0.0001); -- 3.1416
SELECT round(1/3., 0.0001); -- 0.33330000000000004 (ops!)
为避免浮点截断(内部信息丢失),您可以“清理”结果,例如截断 9 位数字:
CREATE or replace FUNCTION ROUND9(
input float, -- the input number
accuracy float -- accuracy
) RETURNS float AS $f$
SELECT (ROUND($1/accuracy)*accuracy)::numeric(99,9)::float
$f$ language SQL IMMUTABLE;
尝试
SELECT round9(1/3., 0.00001); -- 0.33333 float, solved!
SELECT round9(1/3., 0.005); -- 0.335 float, ok!
PS:命令\df round
,在psql
重载后,将显示类似这个表的内容
架构 | 姓名 | 结果 | 争论
------------+-------+------------+------------------
架构 | 圆| 数字 | 浮点数,整数
架构 | 圆| 浮动 | 漂浮,漂浮
pg_catalog | 圆| 浮动 | 漂浮
pg_catalog | 圆| 数字 | 数字
pg_catalog | 圆| 数字 | 数字,整数
其中float是同义词,double precision
而myschema是public
当您不使用模式时。这些pg_catalog
函数是默认函数,请参阅指南内置数学函数。
更多细节
在此处查看完整的Wiki 答案。