PostgreSQL12中浮点数输出算法优化带来的小问题

最近碰到同事发来这样两个SQL,开发反馈输出的结果异常。

复制代码
bill=# select 0.1284*100::float;
      ?column?
--------------------
 12.839999999999998
(1 row)


bill=# select (0.1284*100)::float;
 float8
--------
  12.84
(1 row)

乍一看其实能看出明显的区别,由于::符号的优先级是高于*的,所以没加括号导致结果不同。但是对于第一个SQL输出的结果却很奇怪,为什么会输出这样一个数字?而且将0.1284改成0.1184也不会有问题,这就让人有点费解了。

复制代码
bill=# select 0.1184*100::float;
 ?column?
----------
    11.84
(1 row)

于是我在几个不同版本的pg实例中测试了下,发现pg12及以后的版本均有这种情况,于是看了下12的release notes,发现如下的更新

可以看到,在pg12中使用新的算法输出real和double precision值来提高性能。同时对于extra_float_digits这个参数也有原先默认的0改成了现在默认为1。关于这个参数的含义及用法之前我也有写过文章说明过,这里就不在阐述。

按照官方建议,可以将该参数设置为0与原先低版本保持一致。

复制代码
bill=# show extra_float_digits ;
 extra_float_digits
--------------------
 1
(1 row)


bill=# set extra_float_digits = 0;
SET
bill=#  select 0.1284*100::float;
 ?column?
----------
    12.84
(1 row)

那么还有最后一个问题,为什么前面会输出12.839999999999998这么一串数字呢?可以看到前面的说明中有提到,当extra_float_digits大于零时(现在是默认值),只输出保留精确二进制值所需的最小数字。

这个是什么意思呢,由于前面我们输出的是float类型,当extra_float_digits=1时最多保留17位,但是由于新的浮点数输出算法,只要二进制相同,那么只保留到能得到该二进制的最小位数即可。

换句话说,12.839999999999998和12.84的二进制值是一样的,大家可以计算下,都是1100.110101110000101001,也就是说对于该数而言,两者是相等的。从下面也可以验证。

复制代码
bill=# select 12.839999999999998::float;
 float8
--------
  12.84
(1 row)
相关推荐
AC赳赳老秦13 分钟前
OpenClaw与思维导图工具联动:自动生成工作规划脑图、拆解任务节点,适配职场管理
java·大数据·服务器·数据库·python·php·openclaw
zhishijike33 分钟前
全国行政区划sql(省市区)
数据库·sql·mysql
KaMeidebaby42 分钟前
卡梅德生物技术快报|单 B 细胞抗体技术:全犬源单抗制备流程、关键参数与性能验证
前端·数据库·其他·百度·新浪微博
KG_LLM图谱增强大模型1 小时前
scHilda:大模型与知识图谱分层融合,突破单细胞分型瓶颈
数据库·人工智能·知识图谱
凯瑟琳.奥古斯特1 小时前
力扣3654:二维矩阵连续空位统计
数据结构·数据库·算法·职场和发展
满昕欢喜1 小时前
SQL Server的概述与安装
数据库·sqlserver
2501_930707781 小时前
使用C#代码在 Excel 中为数据透视表添加筛选器
数据库·数据挖掘·数据分析
TDengine (老段)1 小时前
TDengine 数据库创建与参数详解
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
IT策士2 小时前
Django 从 0 到 1 打造完整电商平台:电商项目需求分析与数据库设计
数据库·django·需求分析
阳光九叶草LXGZXJ2 小时前
达梦数据库-学习-52-DmDrs参数介绍(Manager模块)
linux·运维·数据库·sql·学习