‌Python开发者必学:如何优雅地绕过round函数的四舍五入陷阱

news2024/12/22 20:02:03

在这里插入图片描述

引言

在最近交付测试的一个功能中,测试同学反馈一个数据统计四舍五入的问题,问题有点魔性:同样的条件,有的值可以四舍五入成功,有的值直接被舍弃。
例如2.5四舍五入整数直接变成了2;3.5却变成了4。因为使用Python自带的round函数,没有发现问题的出现点在哪里。

    # 2.45四舍五入的结果:2
    print(f"2.45四舍五入的结果:{round(2.15)}")
    # 2.5四舍五入的结果:2
    print(f"2.5四舍五入的结果:{round(2.5)}")
    # 3.5四舍五入的结果:4
    print(f"3.5四舍五入的结果:{round(3.5)}")
    # 3.45四舍五入的结果:3
    print(f"3.45四舍五入的结果:{round(3.45)}")  

在这里插入图片描述

为了更好的解决这个问题,这里把相关情况进行汇总记录。

在这里插入图片描述

原因分析

  1. 浮点数的表示:浮点数在计算机中是以二进制形式存储的,有些十进制小数在二进制中无法精确表示,因此会存在微小的舍入误差。这种误差在大多数情况下是微不足道的,但在进行四舍五入时可能会变得明显。

  2. 四舍五入规则:Python的round()函数遵循“银行家舍入”规则,也称为“向偶数舍入”。这意味着当数值位于两个整数正中间时(即.5的情况),它会舍入到最近的偶数。这与传统的四舍五入规则(总是向上舍入)略有不同。

“银行家舍入”规则
“银行家舍入”规则,又称为“四舍六入五取偶”(或“四舍六入五留双”)法,是一种在金融和计算机科学领域广泛使用的浮点数取整算法。该规则由IEEE 754标准规定,并被大多数编程软件所采用。其核心思想是在保持数据特性方面优于传统的四舍五入法,特别是在处理大量数据时,能够更有效地减少因舍入而产生的误差累积。

银行家舍入规则的具体计算方法如下:

  1. 小于五时舍去:当需要修约的数字小于5时,直接舍去该数字。

  2. 大于五时进位:当需要修约的数字大于或等于6时,在舍去该数字的同时,向前一位进1。

  3. 等于五时特殊处理

  • 如果5后面还有不为0的任何数字,则无论5前面的数字是奇数还是偶数,都向前一位进1。
  • 如果5后面没有数字或所有数字都是0,则需要看5前面的数字。如果5前面是奇数,则向前一位进1;如果5前面是偶数(包括0,因为0也是偶数),则舍去5。

这种规则的优点在于,它能够在一定程度上减少由于简单四舍五入而导致的偏差积累,特别是在处理大量数据时,能够保持数据的统计特性更加稳定。

银行家舍入规则在金融领域的应用非常广泛,包括但不限于贷款、存款、投资、股票交易等场景。在这些场景中,精确的数值计算对于确保金融交易的公平性和可靠性至关重要。通过使用银行家舍入规则,金融机构可以更有效地管理风险,减少因计算误差而导致的损失。

此外,在计算机科学中,特别是在处理浮点数运算时,银行家舍入规则也是一种常用的取整方法。由于浮点数的表示和运算本身就存在精度问题,因此选择合适的舍入方法对于确保计算结果的准确性和可靠性具有重要意义。银行家舍入规则正是基于这一需求而设计的。

在这里插入图片描述

示例

print(round(2.5))  # 输出 2,因为2是偶数
print(round(3.5))  # 输出 4,因为4是偶数
print(round(2.6))  # 输出 3,正常四舍五入

但是,由于浮点数的表示问题,你可能会遇到这样的情况:

print(round(0.5 + 2.5))  # 理论上应该是3.0,但由于浮点数的表示,结果可能不是完全精确的3.0

在这个例子中,0.5 + 2.5 的结果可能由于浮点数的微小误差而略大于 3.0,但非常接近。然而,由于round()函数遵循银行家舍入规则,并且输入值足够接近 3.0,因此它仍然会正确地输出 3。但是,如果你遇到了看似不正确的结果,那很可能是因为浮点数的表示误差。
在这里插入图片描述

解决方案

  1. 使用decimal模块:如果你需要处理高精度的十进制数,并且希望避免浮点数带来的问题,可以使用decimal模块。decimal.Decimal类型提供了对十进制数的精确控制,包括舍入模式。

    from decimal import Decimal, ROUND_HALF_UP
    
    a = Decimal('2.5')
    rounded_a = a.quantize(Decimal('1'), rounding=ROUND_HALF_UP)
    print(rounded_a)  # 输出 3,使用传统的四舍五入规则
    
  2. 理解并接受浮点数的限制:对于大多数日常应用来说,浮点数的微小误差是可以接受的。只需了解并接受这一限制即可。

  3. 增加测试:在开发涉及浮点数的应用程序时,增加对边界情况和异常情况的测试,以确保你的代码能够正确处理这些情况。

  4. 格式化输出:如果你只是需要控制输出的格式(而不是实际的数值精度),你可以使用字符串格式化来四舍五入到特定的小数位数,并控制输出的显示。

    print(f"{2.54567:.0f}")  # 输出 3,使用格式化字符串进行四舍五入
    

在这里插入图片描述

总结

总之,round(a, 0) 在Python 中通常能按预期工作,但如果你遇到了看似不正确的结果,很可能是因为浮点数的表示误差或四舍五入规则造成的。通过了解这些限制并采取相应的解决方案,你可以有效地处理这些问题。

在这里插入图片描述

参考内容

在Python里想要四舍五入有多麻烦?

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

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

相关文章

IDEA 模板配置

IDEA 模板配置 一、tkMapper通用mapper配置 1 新建配置文件generatorConfig.xml&#xff0c;路径src/main/resources/generator/generatorConfig.xml <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE generatorConfigurationPUBLIC "-…

基于单片机的多功能电子钟设计

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP…

C学习(数据结构)-->排序

目录 一、直接插入排序 二、希尔排序 三、直接选择排序 四、快速排序 1、取基准值 1&#xff09;hoare找基准值​编辑 2&#xff09; 挖坑法找基准值​编辑 3&#xff09;快慢指针找基准值​编辑 2、递归快速排序 3、非递归快速排序 ​编辑 五、归并排序 ​编辑 六、计…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 9月7日,星期六

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年9月7日 星期六 农历八月初五 白露 1、 司法部&#xff1a;遏制地方乱发文、出台“奇葩”政策文件等情况。 2、 证监会&#xff1a;拉长离职人员入股禁止期至10年&#xff0c;扩大对离职人员从严监管范围。 3、 全国医护比…

三文带你轻松上手鸿蒙的AI语音03-文本合成声音

三文带你轻松上手鸿蒙的AI语音03-文本合成声音 前言 接上文 三文带你轻松上手鸿蒙的AI语音02-声音文件转文本 HarmonyOS NEXT 提供的AI 文本合并语音功能&#xff0c;可以将一段不超过10000字符的文本合成为语音并进行播报。 场景举例 手机在无网状态下&#xff0c;系统应用…

超声波测距模块HC-SR04(基于STM32F103C8T6HAL库)

超声波测距模块参考资料 1.电路连接及引脚配置 触发信号PA3只需要输出10us的高电平&#xff0c;所以直接设置成 普通的GPIO端口即可&#xff1b;回响信号使用外部中断&#xff0c;上升沿信号产生外部中断&#xff0c;打开定时器&#xff0c;下降沿再产生一次中断&#xff0c;读…

飞特STS3315基本使用方法

宁天道/FeelECH 01-介绍 串口总线舵机&#xff0c;可以通过一根线将多个舵机串联在一起&#xff0c;一个串口线片可以控制所有的舵机。 内带闭环&#xff0c;可以自定义舵机移动的最大速度&#xff0c;加速度&#xff0c; 可以修改各种模式&#xff0c;满足各种各样的需求&…

OTN光传送网-介绍

1. 引用 OTN光传送网--华为设备_otn传输设备建设方案-CSDN博客 OTN光传送网&#xff08;Optical Transport Network&#xff09;&什么是OTN-CSDN博客 https://zhuanlan.zhihu.com/p/403304019 术语&#xff1a; 英文缩写描述灰光模块彩光模块CWDM&#xff1a;Coarse Wa…

欺诈文本分类检测(十三):交叉训练验证

1. 引言 交叉验证主要讨论的是数据集的划分问题。 通常情况下&#xff0c;我们会采用均匀随机抽样的方式将数据集划分成3个部分——训练集、验证集和测试集&#xff0c;这三个集合不能有交集&#xff0c;常见的比例是8:1:1&#xff08;如同前文我们所作的划分)。这三个数据集…

吉利星座03组卫星发射

北京时间2024年9月6日2时30分&#xff0c;在太原卫星发射中心使用长征六号运载火箭&#xff0c;成功将民营“中国星链”——吉利未来出行星座第三个轨道面、吉利星座03组卫星发射升空&#xff0c;10颗卫星顺利进入预定轨道&#xff0c;发射任务获得圆满成功。此次任务是长征系列…

飞思相机存储卡格式化数据如何恢复?提供全面指南

在数字摄影时代&#xff0c;‌飞思相机以其卓越的成像质量和专业的性能&#xff0c;‌赢得了众多摄影师的青睐。‌然而&#xff0c;‌即使是专业的设备也难免遭遇数据丢失的困境&#xff0c;‌尤其是当存储卡不幸被格式化时。‌面对这一突如其来的灾难&#xff0c;‌许多摄影师…

qt QGraphicsScene场景坐标和场景内GraphicsItem局部坐标的相互转换

为了更清晰地解释场景坐标与局部坐标之间的转换过程&#xff0c;我们可以通过一个简单的实例来演示如何赋值场景坐标&#xff0c;并将其转换为图形项的局部坐标。 实例步骤 假设我们有一个场景 QGraphicsScene 和一个矩形图形项 QGraphicsRectItem&#xff0c;矩形的大小为 1…

Redis进阶(六):缓存

1.缓存 速度快的设备可以作为速度慢的设备的缓存 缓存能够有意义&#xff1a;二八定律&#xff0c;20%的数据可以应对80%的请求 通常使用redis作为数据库的缓存&#xff08;mysql&#xff09; 数据库是非常重要的组件&#xff0c;mysql速度比较慢 因为mysql等数据库&#x…

【 C++ 】类和对象的学习(三)

前言&#xff1a; &#x1f618;我的主页&#xff1a;OMGmyhair-CSDN博客 目录 一、初始化列表 二、类型转换 三、static成员 四、友元 五、内部类 六、匿名对象 一、初始化列表 当我们之前在写构造函数时&#xff0c;我们通常在构造函数内对成员变量进行赋值。但其实还…

系统架构师考试学习笔记第三篇——架构设计高级知识(19)嵌入式系统架构设计理论与实践

本章考点&#xff1a; 第19课时主要学习嵌入式系统架构设计的理论和工作中的实践。根据新版考试大纲&#xff0c;本课时知识点会涉及案例分析题&#xff08;25分&#xff09;。在历年考试中&#xff0c;案例题对该部分内容都有固定考查&#xff0c;综合知识选择题目中有固定分值…

北大港中文腾讯提出ViewCrafter:一张图像就可以制作影视特效和游戏画面!

北大和港中文联合腾讯人工智能实验室提出了 ViewCrafter&#xff0c;这是一种利用视频扩散模型的先验从单个或稀疏图像合成一般场景的高保真新视图的新方法。 可以简单理解为将复杂的图像转换成新角度的图像版本。首先&#xff0c;它会使用特殊的算法来读取一张或几张图像&…

SpringBoot项目-实现简单的CRUD功能和分页查询

背景 本博文主要是创建了一个新的SpringBoot项目&#xff0c;实现基本的增删改查&#xff0c;分页查询&#xff0c;带条件的分页查询功能。是方便初学者学习后端项目的一个比较清晰明了的实践代码&#xff0c;读者可根据博文&#xff0c;从自己动手创建一个新的SpringBoot项目…

Scratch教师节 —— 感恩教师节

小虎鲸Scratch资源站-免费Scratch作品源码,素材,教程分享平台! Scratch教师节动画作品——感恩教师节 在这个特别的日子里&#xff0c;我们迎来了教师节。为了表达对老师们的感激之情&#xff0c;Scratch平台上的小朋友们用创意与热情制作了精彩的动画作品——“感恩教师节”。…

在国产芯片上实现YOLOv5/v8图像AI识别-【4.3】RK3588使用yolov8+bytetrack实现跟踪更多内容见视频

本专栏主要是提供一种国产化图像识别的解决方案&#xff0c;专栏中实现了YOLOv5/v8在国产化芯片上的使用部署&#xff0c;并可以实现网页端实时查看。根据自己的具体需求可以直接产品化部署使用。 B站配套视频&#xff1a;https://www.bilibili.com/video/BV1or421T74f 背景…

【Canvas与艺术】四叶花

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>386.四叶花</title><style type"text/css">.c…