当前位置: 首页 > news >正文

Python 中的 round() 函数不是严格的“四舍五入“,而是采用银行家舍入法(Bankers‘ Rounding)

round()是 Python 的内置函数,用于对数字进行四舍五入。


Python的round()函数采用银行家舍入法(奇进偶不进),而非传统四舍五入。如round(2.5)返回2而非3,这是为了减少统计偏差。


对于需要传统四舍五入的场景,建议使用Decimal模块的ROUND_HALF_UP模式,或自定义函数处理。


注意浮点数精度问题(如2.675可能存储为2.674999...),金融计算推荐使用Decimal保证精度,数据显示可用格式化方法。


银行家舍入法适合科学计算,而商业场景通常需要传统四舍五入规则。


round()函数详解


round()是 Python 的内置函数,用于对数字进行四舍五入。


基本语法

round(number, ndigits=None)
  • number:要四舍五入的数字

  • ndigits:保留的小数位数(可选,默认为 0)

  • 返回值:四舍五入后的数字

基本用法

python

# 不指定小数位数,四舍五入到整数 print(round(3.14)) # 3 print(round(3.5)) # 4 print(round(3.6)) # 4 print(round(-3.5)) # -4(注意负数) # 指定小数位数 print(round(3.14159, 2)) # 3.14 print(round(3.14159, 3)) # 3.142 print(round(3.14159, 0)) # 3.0(返回浮点数)

特殊情况:银行家舍入法

Python 的round()采用银行家舍入法(偶数舍入),当数字正好在中间时,会舍入到最近的偶数:

python

# 四舍五入到整数 print(round(2.5)) # 2(舍入到偶数 2) print(round(3.5)) # 4(舍入到偶数 4) print(round(4.5)) # 4(舍入到偶数 4) print(round(5.5)) # 6(舍入到偶数 6) # 保留一位小数 print(round(2.25, 1)) # 2.2(2.2 和 2.3 中间,舍入到偶数 2.2) print(round(2.35, 1)) # 2.4(2.3 和 2.4 中间,舍入到偶数 2.4) print(round(2.45, 1)) # 2.5(注意:浮点数精度问题)

实际应用场景

1.金额计算(保留两位小数)

python

price = 19.99 quantity = 3 total = price * quantity result = round(total, 2) print(result) # 59.97

2.百分比计算

python

score = 85 total_score = 120 percentage = (score / total_score) * 100 rounded = round(percentage, 1) print(f"得分率:{rounded}%") # 得分率:70.8%

3.格式化输出

python

import math pi = math.pi print(round(pi, 2)) # 3.14 print(round(pi, 4)) # 3.1416

注意事项

1.浮点数精度问题

python

# 浮点数存储可能不精确 print(round(2.675, 2)) # 2.67(不是预期的 2.68) # 原因:2.675 实际存储为 2.6749999999999998

2.ndigits 为负数

python

# 负数表示舍入到十位、百位等 print(round(123.45, -1)) # 120.0(舍入到十位) print(round(123.45, -2)) # 100.0(舍入到百位) print(round(9876, -3)) # 10000(舍入到千位)

3.返回值类型

python

# ndigits 省略或为 None:返回 int print(type(round(3.14))) # <class 'int'> print(type(round(3.14, 0))) # <class 'float'> # ndigits 指定:返回 float print(type(round(3.14, 1))) # <class 'float'>

对比其他方法

python

# 1. round() - 四舍五入 print(round(3.14159, 2)) # 3.14 # 2. format() - 格式化字符串 print(f"{3.14159:.2f}") # 3.14 print("{:.2f}".format(3.14159)) # 3.14 # 3. Decimal - 精确十进制运算 from decimal import Decimal, ROUND_HALF_UP num = Decimal('2.675') print(num.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.68

替代方案:真正的四舍五入

如果需要传统意义的四舍五入(远离零舍入),可以使用decimal模块:

python

from decimal import Decimal, ROUND_HALF_UP def traditional_round(num, digits=0): """传统四舍五入""" num_str = str(num) decimal = Decimal(num_str) return float(decimal.quantize(Decimal('0.' + '0' * digits), rounding=ROUND_HALF_UP)) # 测试 print(traditional_round(2.675, 2)) # 2.68(传统四舍五入) print(round(2.675, 2)) # 2.67(银行家舍入)

总结

  • round()用于四舍五入,但采用银行家舍入法

  • 默认返回整数,指定ndigits返回浮点数

  • 注意浮点数精度问题

  • 金融计算建议使用Decimal模块


Python 中的round()函数不是严格的"四舍五入",而是采用银行家舍入法(Bankers' Rounding)。


核心规则:奇进偶不进


"奇进偶不进"是银行家舍入法的通俗口诀,专门用来处理刚好是中间值(如 0.5, 1.5, 2.5)的情况。


核心含义

当小数部分恰好是 0.5时:

  • 前一位是奇数→ 进位(+1)

  • 前一位是偶数→ 舍去(不进位)

具体例子

# 保留整数(看小数点前一位的奇偶性) 1.5 → 前一位是 1(奇数)→ 进位 → 2 ✅ 2.5 → 前一位是 2(偶数)→ 不进位 → 2 ✅ 3.5 → 前一位是 3(奇数)→ 进位 → 4 ✅ 4.5 → 前一位是 4(偶数)→ 不进位 → 4 ✅ # 保留一位小数(看小数点后第二位) 1.25 → 第二位是 2(偶数)→ 不进位 → 1.2 ✅ 1.35 → 第二位是 3(奇数)→ 进位 → 1.4 ✅ 1.45 → 第二位是 4(偶数)→ 不进位 → 1.4 ✅

python

# 银行家舍入:遇到 .5 时,向最近的偶数舍入 print(round(1.5)) # 2 (1.5 → 最近的偶数是 2) print(round(2.5)) # 2 (2.5 → 最近的偶数是 2) ⚠️ 不是3! print(round(3.5)) # 4 (3.5 → 最近的偶数是 4) print(round(4.5)) # 4 (4.5 → 最近的偶数是 4) # 对比传统四舍五入 # 1.5→2, 2.5→3, 3.5→4, 4.5→5

为什么会这样?

原因:消除统计偏差,让大数据集的总和更准确

python

# 传统四舍五入的偏差 numbers = [1.5, 2.5, 3.5, 4.5] # 传统四舍五入:2 + 3 + 4 + 5 = 14 (偏差 +0.5) # 银行家舍入:2 + 2 + 4 + 4 = 12 (无偏差) # 实际测试 print(sum(round(n) for n in numbers)) # 12

完整示例

python

# 正数情况 print(round(0.5)) # 0 (偶数→0) print(round(1.5)) # 2 (奇数→2) print(round(2.5)) # 2 (偶数→2) # 负数情况(同样规则) print(round(-0.5)) # 0 print(round(-1.5)) # -2 print(round(-2.5)) # -2 # 更多位数的情况 print(round(1.25, 1)) # 1.2 (1.25 → 最近的偶数小数点后1位是2) print(round(1.35, 1)) # 1.4 (1.35 → 3是奇数,进位到4)

如何实现真正的四舍五入?

方法1:使用Decimal模块(推荐)

python

from decimal import Decimal, ROUND_HALF_UP # 真正的四舍五入 def round_half_up(n, decimals=0): factor = Decimal('10') ** (-decimals) return Decimal(str(n)).quantize(factor, rounding=ROUND_HALF_UP) print(round_half_up(2.5)) # 3 print(round_half_up(2.5, 0)) # 3 print(round_half_up(1.25, 1)) # 1.3 # 直接使用 Decimal d = Decimal('2.5') print(d.quantize(Decimal('1'), rounding=ROUND_HALF_UP)) # 3

方法2:自定义函数(简单场景)

python

def traditional_round(n, decimals=0): factor = 10 ** decimals return int(n * factor + (0.5 if n >= 0 else -0.5)) / factor print(traditional_round(2.5)) # 3.0 print(traditional_round(2.5, 0)) # 3.0 print(traditional_round(1.25, 1)) # 1.3 print(traditional_round(-1.5)) # -2.0 (注意负数处理)

方法3:使用math.floormath.ceil

python

import math def round_half_up_alt(n): """正数四舍五入""" return math.floor(n + 0.5) if n >= 0 else math.ceil(n - 0.5) print(round_half_up_alt(2.5)) # 3 print(round_half_up_alt(-2.5)) # -3

注意浮点数精度问题

python

# 浮点数存储不精确 print(round(2.675, 2)) # 2.67 (不是预期的 2.68!) # 因为 2.675 实际存储为 2.6749999999999998 # 解决方案:使用 Decimal from decimal import Decimal print(Decimal('2.675').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.68

实际应用建议

场景推荐方法原因
金融计算Decimal+ROUND_HALF_UP符合商业习惯,精度可控
科学计算round()减少统计偏差
数据显示format()f-string格式化不影响底层数据
简单取整int(x + 0.5)快速,但注意负数

python

# 格式化显示(采用四舍五入显示,但不改变值) print(f"{2.5:.0f}") # 2 (注意:格式化也是银行家舍入!) print(f"{2.5:.0f}") # 2 # 使用 format() print(format(2.5, '.0f')) # 2

总结:Python 默认使用银行家舍入法,需要传统四舍五入时请使用Decimal模块。

http://www.jsqmd.com/news/674881/

相关文章:

  • MFC 去掉CSV文件(指定文件路径)末尾的换行符
  • 保姆级教程:从OpenWrt编译目录里精准找到你的路由器固件(以MT7688/小米路由为例)
  • 2026年3月pe管公司口碑推荐,双壁波纹管/pe波纹管/pe管/钢带管/玻璃钢夹砂管/玻璃钢管,pe管厂商找哪家 - 品牌推荐师
  • Cesium加载ArcGIS WMTS服务踩坑实录:从Capabilities.xml到tileMatrixLabels的完整避坑指南
  • 无人机送货时如何‘看’得更远?聊聊MPC里的预测时域K和采样时间dt怎么调
  • 手把手教你用CAN DiVa测试ISO 15765-2传输层:从TP1到TP39的实战避坑指南
  • FineReport实战:如何用下拉复选框+存储过程搞定报表数据的动态状态切换(附完整代码)
  • 规划失败怎么办:回退、改写与再规划策略
  • 从训练到部署:手把手教你将MaixHub生成的kmodel模型烧录到K210开发板运行
  • GTE中文嵌入模型开源镜像:含完整USAGE.md文档与典型错误解决方案
  • Conan实战:如何把本地编译好的cJSON库(Linux ARM平台)一键发布为团队共享包
  • 喜马拉雅音频下载器:三步搞定VIP付费内容本地保存
  • 2026年高性价比的本溪旅游/本溪旅游徒步游宝藏亲子地推荐 - 行业平台推荐
  • 从一次真实的应急响应说起:我们是如何通过异常图片上传流量发现被入侵的JunAMS服务器
  • VSPD虚拟串口的5个高级用法:从基础调试到TCP/IP设备模拟
  • 别再暴力搜索了!用‘可行性剪枝’5分钟搞定洛谷P1025数的划分
  • 软考高项通关:项目管理核心英语术语与真题精解
  • 别再死记命令了!通过eNSP抓包,带你真正看懂路由器和三层交换机下发DHCP的全过程
  • 逆向工程的边界:当技术探索遇见商业限速的博弈
  • 2026年质量好的广东拉力测试机/材料拉力测试/拉力测试机优质厂家推荐榜 - 品牌宣传支持者
  • 2026年比较好的湿式静电/高压湿式静电/湿式静电除尘/高压湿式静电净化器厂家选择推荐 - 品牌宣传支持者
  • 【Element】el-select远程搜索进阶:自定义搜索逻辑与后端接口高效联调实战
  • 采购申请创建后如何修改?SAP ABAP中BAPI_PR_CHANGE的实用指南与常见问题
  • 别再只调MoveIt!了,手把手教你用OMPL为机械臂定制专属规划器(附Python/C++代码)
  • 从数据到形变图:SARScape D-InSAR全流程实战解析
  • 2026年3月国内光伏电站清洗口碑推荐,助力光伏电站高效运维,光伏电站安装/储能电站安装,光伏电站运维生产厂家哪个好 - 品牌推荐师
  • 2026水处理设备选购攻略:除铁锰厂家实力比拼,离子交换设备/净水设备/混床设备/反渗透膜,水处理设备工厂有哪些 - 品牌推荐师
  • 乾云科技连续三年荣登中国边缘计算企业20强,以云边端安协同发展书写持续领跑的行业答卷
  • ADSP21489之CCES开发笔记(七):SPORT多协议配置与SRU信号路由实战
  • 别再手动算面积了!用Shapely+GeoPandas轻松处理GeoJSON地理数据