PostgreSQL - 从双精度字段中获取所有整数数字以用于 to_char 函数

Posted

技术标签:

【中文标题】PostgreSQL - 从双精度字段中获取所有整数数字以用于 to_char 函数【英文标题】:PostgreSQL - get all integer digits from double precision field for use in to_char function 【发布时间】:2015-05-28 16:48:35 【问题描述】:

正如documentation of Postgres 9.0 中所述,double precision 数据类型具有 15 个十进制数字的精度和 8 个字节的存储空间,然后是一个大于普通 bigint(8 个字节)的整数,存储在 @987654324 中@字段是近似的。如果我错了,请纠正我,我说大于正常的 bigint,因为如果您尝试将此数字转换为 bigint,则会收到此错误:

select 211116514527303268704::bigint;
>> ERROR:  bigint out of range

当您尝试将其转换为 double precisionnumeric 并比较两者时,您会发现它们是相同的:

select 211116514527303268704::numeric,
211116514527303268704::double precision,
(211116514527303268704::double precision) = (211116514527303268704::numeric);
+-----------------------+----------------------+---------+
|        numeric        |        float8        | boolean |
+-----------------------+----------------------+---------+
| 211116514527303268704 | 2.11116514527303e+20 | t       |
+-----------------------+----------------------+---------+

使用to_char() 函数,它们返回不同的值:

select
trim(to_char((211116514527303268704::double precision),'999,999,999,999,999,999,999')),
trim(to_char((211116514527303268704::numeric),'999,999,999,999,999,999,999'));
+-----------------------------+-----------------------------+
|            text             |            text             |
+-----------------------------+-----------------------------+
| 211,116,514,527,303,270,400 | 211,116,514,527,303,268,704 |
+-----------------------------+-----------------------------+

如您所见,使用 to_char - 数字组合返回的值是正确的,但 to_char - 双精度与 double precision 2.11116514527303e+20 中的指数部分失去一致性

我不确定它是否会影响某些东西,但 lc_numeric 的语言环境是 'es_PY.utf8'

在这种情况下实现double precision 完全没用,还是保留这些双精度字段的另一种选择?这始终是首选选项,有某种类型的从 double precisionnumeric 的转换可以保留所有原始数字?

有关更多信息,我在 CentOS 6 x86-64 服务器上运行了 PostgreSQL 9.0 安装。

【问题讨论】:

【参考方案1】:

原因是为了相等比较,将分辨率较高的类型转换为分辨率较低的类型。即:在示例中,numeric 被强制转换为 double precision

演示:

SELECT *
     , num = dp          AS no_cast
     , num::float8 = dp  AS dp_cast
     , num = dp::numeric AS num_cast
FROM  (
   SELECT numeric '211116514527303268705' AS num
        , float8  '211116514527303268705' AS dp
   ) t;

 num                  | dp                    | no_cast | dp_cast | num_cast
----------------------+-----------------------+---------+---------+---------
211116514527303268705 | 2.11116514527303e+020 | t       | t       | f

float8double precision 的别名。 请注意,对于其他计算,例如加法,具有更高 分辨率的类型是结果 - 这是逻辑必需的。 (这里的结果无论如何都是boolean。)

【讨论】:

是的,我注意到从 float8 到 numeric 的强制转换给出了另一个结果,然后超过 8 个字节限制的部分永远不会恢复,如果我想要,numeric 数据类型是唯一的方法保留所有值,如果我错了,请纠正我,感谢您的快速回复! @Osuka:你是对的。 numeric 是标准 Postgres 中唯一的数据类型。 谢谢!当我提高我的声誉时,我会给你一个赞成票

以上是关于PostgreSQL - 从双精度字段中获取所有整数数字以用于 to_char 函数的主要内容,如果未能解决你的问题,请参考以下文章

从双数组中获取最小值不起作用

将工作代码从双精度转换为四精度:如何从输入文件中读取 FORTRAN 中的四精度数字

在c ++中从双精度转换为字符串[重复]

为啥Java在使用“加号”运算符时会执行从双精度到整数的隐式类型转换? [复制]

PostgreSQL获取table名,字段名

在PostgreSQL中分隔整数值