10

我有一个关于 PostgreSQL 9.2 中浮点数的新手问题。

是否有直接舍入浮点数的功能,即无需先将数字转换为数字类型?

另外,我想知道是否有一个函数可以按任意度量单位进行舍入,例如最接近 0.05?

首先将数字转换为十进制形式时,以下查询完美运行:

SELECT round(1/3.::numeric,4);

 round  
--------
 0.3333
(1 row)
Time: 0.917 ms

但是,我真正想要实现的是以下内容:

SELECT round(1/3.::float,4);

目前给我以下错误:

ERROR:  function round(double precision, integer) does not exist at character 8
Time: 0.949 ms

谢谢

4

2 回答 2

14

您的解决方案适用于任何版本的 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 precisionmyschemapublic当您不使用模式时。这些pg_catalog函数是默认函数,请参阅指南内置数学函数


更多细节

在此处查看完整的Wiki 答案

于 2014-01-05T13:06:08.813 回答
13

您可以通过执行以下操作来完成此操作

select round( (21.04 /0.05 ),0)*0.05

其中21.04是要四舍五入的数字,0.05是准确度。

于 2013-04-27T00:12:17.990 回答