【openGauss】OPENGAUSS/POSTGRESQL 中float类型到int类型的隐式转换

news2024/10/21 16:36:23

下面这条sql在oracle和POSTGRESQL/OPENGAUSS中的查询结果不一致

select  cast(cast(0.5 as float) as integer);

在oracle中返回1,在openGauss中返回0,咋一看好像是openGauss中使用了截断的方式,但是如果执行

select  cast(cast(1.5 as float) as integer);

则会发现oracle和openGauss中同样返回了2,这个时候就会猜想是不是这个float类型在两个数据库中实现并不一样导致的,因为ORACLE的float是按number格式存储的,不是标准定义中的浮点类型,而是一种精确类型;而openGauss中的float符合标准定义的浮点类型,是一种非精确类型。
但我们并不能妄下这种判断,多测几组数据:

select 
 cast(cast(0.5 as float) as integer) c1 ,
 cast(cast(0.6 as float) as integer) c2 ,
 cast(cast(1.5 as float) as integer) c3,
 cast(cast(2.5 as float) as integer) c4,
 cast(cast(3.5 as float) as integer) c5, 
 cast(cast(4.5 as float) as integer) c6
c1c2c3c4c5c6
012244

从这组数据中发现一个规律,当小数尾数为5进行舍入时,前一位总是偶数,这自然联想到了另一种四舍五入算法,即银行家算法,对应ORACLE12C新增的一个函数round_ties_to_even。

openGauss数据库是开源的,我们完全可以通过查看源码来验证我们的猜想。

接下来开始就是说明如何通过这种问题来找到对应的源码逻辑。

首先要知道一些openGauss的元数据基础知识。
openGauss的元数据基本继承postgresql,所以这个知识可以复用。
在postgresql中,几乎所有的类型、函数、操作符、规则等,都可以在元数据表中查到。对于类型转换,即cast,也有一张对应的表,即pg_cast,下面这个SQL就是查询从float8到int8是否存在直接的类型转换规则

select * from pg_cast h 
where h.castsource ='float8'::regtype 
and h.casttarget ='int8'::regtype;
castsourcecasttargetcastfunccastcontextcastmethodcastowner
70120483if

查到了是有的,这里castmethod为f,表示这个转换是使用某个函数进行转换的,一般是二进制存储结构有变更才会需要使用到函数。然后castfunc即为这个转换函数的oid,接下来我们去查这是用的哪个函数

select proname,prosrc from pg_proc where oid=483;
pronameprosrc
int8dtoi8

可以看到使用的是int8函数,然后int8的函数源码是dtoi8,此时我们就可以去openGauss源码中搜索dtoi8了,
找到了
.\openGauss-server\src\common\backend\utils\adt\int8.cpp

/* dtoi8()
 * Convert float8 to 8-byte integer.
 */
Datum dtoi8(PG_FUNCTION_ARGS)
{
    float8 num = PG_GETARG_FLOAT8(0);

    /*
     * Get rid of any fractional part in the input.  This is so we don't fail
     * on just-out-of-range values that would round into range.  Note
     * assumption that rint() will pass through a NaN or Inf unchanged.
     */
    num = rint(num);

    /*
     * Range check.  We must be careful here that the boundary values are
     * expressed exactly in the float domain.  We expect PG_INT64_MIN  to be an
     * exact power of 2, so it will be represented exactly; but PG_INT64_MAX
     * isn't, and might get rounded off, so avoid using it.
     */
    if (num < (float8)PG_INT64_MIN || num >= -((float8)PG_INT64_MIN) || isnan(num)) {
        if (fcinfo->can_ignore && !isnan(num)) {
            ereport(WARNING, (errmsg("bigint out of range")));
            PG_RETURN_INT64(num < (float8)PG_INT64_MIN ? LONG_MIN : LONG_MAX);
        }
        ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range")));
    }

    PG_RETURN_INT64((int64)num);
}

这段代码注释加警告比实际逻辑还多,但真正要看的只有 num = rint(num);这一行,这里又引用到了rint函数,点进去

double rint(double x)
{
    return (x >= 0.0) ? floor(x + 0.5) : ceil(x - 0.5);
}

如果不是开发人员,对这种计算看不懂,可以借助AI

这段代码定义了一个名为 rint 的函数,用于将一个双精度浮点数 x 四舍五入到最接近的整数。具体来说:
如果 x 大于或等于 0.0,则返回 floor(x + 0.5),即将 x 加上 0.5 后向下取整。
如果 x 小于 0.0,则返回 ceil(x - 0.5),即将 x 减去 0.5 后向上取整。
这样可以实现对正数和负数的四舍五入。

这样就否定了之前的猜想,这里是按照常规的算法进行四舍五入的,但结果竟然和银行家算法一样。
于是我们回到最初的猜想,这个问题仍然与不精确的浮点类型有关,其实ORACLE也有这种浮点类型,叫binary_float和binary_double,这两个类型不能在sql中使用,只能在plsql中使用,我们写个简单的例子在ORACLE进行测试

declare
x binary_integer;
begin
select  cast(0.5 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(0.6 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(1.5 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(2.5 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(3.5 as binary_double) into x from dual;
dbms_output.put_line(x);
end;

0
0
1
2
3

竟然出现了第三种结果,即全部都是按trunc

再把binary_integer改成integer,再在ORACLE中测试

declare
x integer;
begin
select  cast(0.5 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(0.6 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(1.5 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(2.5 as binary_double) into x from dual;
dbms_output.put_line(x);
select  cast(3.5 as binary_double) into x from dual;
dbms_output.put_line(x);
end;

.5
.59999999999999998
1.5
2.5
3.5

出现了第四种结果!ORACLE的integer竟然能显示出小数!

我们理解不同的数据类型可以有不同的表现行为,也知道oracle中的integer其实是按number类型进行的实现,但是这明晃晃的声明了integer类型竟然还能打印出小数,这对于应用开发者来说如何能够接受?
当然,我们可以认为这个用例的用法是不合理的,正常情况下小数转换成整数应该使用函数来处理,而不是通过类型转换。也可能之前从来没有人这么用过,所以ORACLE一直没发现存在这个问题。

于是回到最开始的问题上,openGauss/postgresql和ORACLE表现不一致,究竟谁是对的,或许我们永远都无法找到准确答案,这只能算是一种行为差异,并且都可以解释得通。但在看到ORACLE换个方式出现了第三种结果,甚至还出现了整数类型显示小数这种奇葩BUG时,ORACLE的权威性陡然下降。

为了避免这种问题,建议无论在用什么数据库时,对于类型转换,还是慎重一些为好

  • 本文作者: DarkAthena
  • 本文链接: https://www.darkathena.top/archives/opengauss-float2int-cast-round
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2220155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024 OSCAR|《开源体系建设路径模式洞察与建议》即将发布

近年来&#xff0c;开源体系建设受到高度重视&#xff0c;国家软件发展战略和“十四五”规划纲要均对开源作出重要部署&#xff0c;为我国开源体系建设和发展指明了方向。9月25日&#xff0c;工业和信息化部党组书记、部长金壮指出要加强开源体系建设&#xff0c;助推产业高质量…

03 springboot-国际化

Spring Boot 提供了很好的国际化支持&#xff0c;可以轻松地实现中英文国际化。 项目创建&#xff0c;及其springboot系列相关知识点详见&#xff1a;springboot系列 springboot系列&#xff0c;最近持续更新中&#xff0c;如需要请关注 如果你觉得我分享的内容或者我的努力对…

构建高效房屋租赁平台:SpringBoot应用案例

第1章 绪论 1.1 课题背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。所以各行业&#xff0c;尤其是规模较大的企业和学校等…

爱维艾夫净利润下滑权益回报率骤降,退款数量增加市占率仅1%

《港湾商业观察》施子夫 9月13日&#xff0c;爱维艾夫医院管理集团有限公司&#xff08;以下简称&#xff0c;爱维艾夫&#xff09;第二次递表港交所&#xff0c;保荐机构为中信证券。 爱维艾夫的第一次递表发生在2023年12月&#xff0c;后因递表资料失效而告终。一年不到的时…

基于SSM机场网上订票系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;机票信息管理&#xff0c;订单信息管理&#xff0c;机场广告管理&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;机票信息&#xf…

餐饮行业有什么好的供应链管理系统

在餐饮企业的供应链管理中&#xff0c;合适的供应链管理系统是至关重要的&#xff0c;它能够帮助企业提高食材采购效率、降低成本、确保食材供应的及时性和质量。然而&#xff0c;许多餐饮企业在供应链管理系统方面存在诸多问题&#xff0c;常常会面临以下困境&#xff1a; ●…

【路径跟踪控制:Bang-Bang 控制与车辆运动学模型】

【路径跟踪控制&#xff1a;Bang-Bang 控制与车辆运动学模型】 1. 引言2. 环境准备3. 车辆运动学模型3.1 理论基础3.2 Python 实现车辆运动学模型建模 4. Bang-Bang 控制策略4.1 理论基础4.1.1 误差角度计算与转向角调整4.1.2 Bang-Bang控制实现 4.2 完整代码4.3 控制策略解释 …

springboot051医院管理系统(论文+源码)_kaic

医院管理系统 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系统的系统分析部分&#…

万家数科:零售业务信息化融合的探索|OceanBase案例

本文作者&#xff1a;马琳&#xff0c;万家数科数据库专家。 万家数科商业数据有限公司&#xff0c;作为华润万家旗下的信息技术企业&#xff0c;专注于零售行业&#xff0c;在为华润万家提供服务的同时&#xff0c;也积极面向市场&#xff0c;为零售商及其生态系统提供全面的核…

基于DSP+ARM+FPGA的电能质量分析仪的软件设计

软件设计是电能质量设备的核心内容&#xff0c;上述章节详细介绍了电能质量参数的 算法&#xff0c;并且通过仿真实验进行了验证&#xff0c;本章将结合现代电能质量监测设备需求实 现算法在实际电网中应用。根据设计的电能质量分析仪的需求分析&#xff0c;进行总体的 软件…

【Android】Jetpack入门知识总结(LifeCycle,ViewModel,LiveData,DataBinding等)

文章目录 LifeCycle使用Lifecycle解耦页面与组件自定义控件实现LifecycleObserver接口注册生命周期监听器 使用LifecycleService解耦Service与组件使用ProcessLifecycleOwner监听应用程序生命周期 ViewModel用法在 Fragment 中使用 ViewModel LiveDataDataBinding导入依赖基本用…

Redis 性能优化选择:Pika 的配置与使用详解

引言 在我们日常开发中 redis是我们开发业务场景中不可缺少的部分。Redis 凭借其内存存储和快速响应的特点&#xff0c;广泛应用于缓存、消息队列等各种业务场景。然而&#xff0c;随着数据量的不断增长&#xff0c;单节点的 Redis 因为内存限制和并发能力的局限&#xff0c;逐…

FP7127:降压恒流LED芯片 支持双路调色调光 PWM调光

一、降压恒流LED芯片FP7127 FP7127 是平均电流模式控制的 LED 驱动 IC&#xff0c;具有稳定输出恒流的能力&#xff0c;优秀的负载调整率与高精度的电流控制。不用额外增加外部补偿元件&#xff0c;简化 PCB 板设计。输出的LED电流精度为 2%。 如果你想进行PWM数位调光&#…

R语言机器学习教程大纲

文章目录 介绍机器学习算法监督学习Supervised Learning分类Classification回归Regression 无监督学习 Unsupervised Learning聚类 Clustering降纬 Dimensionality Reduction相关Association 强化学习Reinforcement Learning模型自由 Model-Free Methods模型驱动 Model-Based M…

Rancher—多集群Kubernetes管理平台

目录 一、Rancher 简介1.1 Rancher 和 k8s 的区别 二、Rancher 安装及配置2.1 安装 rancher2.2 登录 Rancher 平台2.3 Rancher 管理已存在的 k8s 集群2.4 创建名称空间 namespace2.5 创建 Deployment 资源2.6 创建 service2.7 Rancher 部署监控系统 一、Rancher 简介 Rancher …

curl支持ssl错误:curl: (60) SSL certificate problem: certificate is not yet valid

在测试curl命令的时候发现curl: (60) SSL certificate problem: certificate is not yet valid出现这个错误&#xff0c;已经设置了ssl证书路径&#xff0c;最终发现是板子上时间不对&#xff0c;设置时间后可以正常使用。

论文研读 | End-to-End Object Detection with Transformers

DETR&#xff1a;端到端目标检测的创新 —— 作者 Nicolas Carion 等人 一、背景与挑战 目标检测是计算机视觉领域的一个核心任务&#xff0c;要求模型精确识别图像中的物体类别和位置。传统方法如 Faster R-CNN&#xff0c;因其区域建议网络等复杂结构&#xff0c;使得模型调…

网络安全基础知识点_网络安全知识基础知识篇

文章目录 一、网络安全概述1.1 定义1.2 信息安全特性1.3 网络安全的威胁1.4 网络安全的特征 二、入侵方式2.1 黑客2.1.1 入侵方法2.1.2 系统的威胁2.2 IP欺骗与防范2.2.1 TCP等IP欺骗基础知识2.2.2 IP欺骗可行的原因2.2.3 IP欺骗过程2.2.4 IP欺骗原理2.2.5 IP欺骗防范2.3 Sniff…

数据结构编程实践20讲(Python版)—16有向图

本文目录 16 有向图(Directed Graph)S1 说明特征应用领域S2 示例S3 问题:利用有向图构建贝叶斯网络Python代码代码说明结果S4 问题:有依赖的任务调度Python代码代码说明结果S5 问题:基于有向图的搜索引擎排序算法Python代码代码说明结果往期链接 01 数组02 链表03 栈04 队…

成都睿明智科技有限公司电商服务可靠不?

在这个短视频风起云涌的时代&#xff0c;抖音不仅成为了人们娱乐消遣的首选平台&#xff0c;更是众多商家竞相追逐的电商新蓝海。成都睿明智科技有限公司&#xff0c;作为抖音电商服务领域的佼佼者&#xff0c;正以其独到的洞察力和专业的服务&#xff0c;助力无数品牌在这片沃…