python四舍五入(round精度不够,有时不能实现四舍五入)


Python 所有文章传送门
【Python】所有文章传送门

目录

  • 简述 / 前言
  • 1. Python 实验
  • 2. 自定义函数
  • 3. 总结

简述 / 前言

最近心血来潮,刚复习到折半插入排序时,发现算法的mid(中间点)选择的公式是:(low + high)/2,那么当(low + high)出现奇数时怎么办呢,比如(low + high)/2 = 1.5,那么是取 1 还是 2 呢?于是我在 Python 中实验了一下,由于 Python 中浮点数运算结果还是浮点数,因此我用了内置函数 round(number, ndigits) 来实现小数转整数运算。

1. Python 实验

>>> round(1.5, 0)
2.0

看样子好像是四舍五入的取法,但是换了一个数字之后,就发现新大陆了!

>>> round(2.5, 0)
2.0

这个运算发现round其实就是直接截取了整数部分,那么事实果真如此吗?文末会给出解答~

2. 自定义函数

第一反应就是官方的函数是不是有问题,于是找了几篇博客(参考的一个博客解答,但并没有完全解决)看看怎么回事,发现给出的解决方法都不能解决问题,实验如下:

>>> from decimal import Decimal
>>>
>>> print(round(Decimal("1.5"),0))
2
>>> print(round(Decimal("2.5"),0))
2
>>> print(Decimal("1.5").quantize(Decimal("0.")))
2
>>> print(Decimal("2.5").quantize(Decimal("0.")))
2

于是一股脑的自己花了十几分钟写了一个函数来实现:

def round_Pro(number, ndigits):"""实现四舍五入:param number: 要四舍五入的数字:param ndigits: 要保留的位数:return: 以 float 形式输出"""flag = ''       # 用于记录 number 的正负性if number < 0:flag = '-'number_abs = abs(number)    # 一律采用正数的四舍五入进行操作number_abs_str = str(number_abs)if '.' in number_abs_str:       # 如果给的数字是小数的话integer = int(number_abs_str.split('.')[0])     # 数字的整数部分decimal_str = number_abs_str.split('.')[1]      # 数字的小数部分decimal_cnt = len(decimal_str)      # 小数位数if ndigits >= decimal_cnt:      # 如果要保留的小数位数 >= 整个小数位数,则直接输出原数字return numberelse:       # 要保留的小数位数 < 整个小数位数,需要进行四舍五入judge_num = int(decimal_str[ndigits])   # 舍入位数字(根据此数字判断是否需要进位)if ndigits == 0:    # 只保留整数decimal = 0     # 小数设为 0if judge_num >= 5:  # 如果小数第一位 > 5,则整数进一位integer += 1else:       # 保留指定小数位数decimal = int(decimal_str[:ndigits])        # 要保留的小数(直接截断转为整数,便于后续直接计算进位)decimal_cnt = len(decimal_str[:ndigits])    # 要保留的小数位数if judge_num >= 5:      # 如果判断位(指定保留小数位数后一位的小数数字,比如:number=1.234,ndigits=2,那么判断位就是数字"4") > 5decimal += 1        # 小数进一位if len(str(decimal)) > decimal_cnt:     # 如果进位导致小数位最高位也进位了integer += 1        # 整数部分也要进位decimal = str(decimal)[1:]      # 小数部分去掉最高位(由于进位多出来的数据)decimal = str(decimal)return float(flag + str(integer) + '.' + decimal)else:       # 给的数字是一个整数,直接输出return number

测试如下:

print(round_Pro(2.9897, 5))
print(round_Pro(2.4497, 1))
print(round_Pro(2.4497, 0))
print(round_Pro(2.5597, 0))
print(round_Pro(2.5597, 10))
print(round_Pro(0, 0))
print(round_Pro(0, 10))
print(round_Pro(-1.5, 0))
print(round_Pro(-1.5, 1))
print(round_Pro(-1.56, 1))
print(round_Pro(-1.56, 2))
print(round_Pro(-1.999, 2))

输出如下:

2.9897
2.4
2.0
3.0
2.5597
0
0
-2.0
-1.5
-1.6
-1.56
-2.0

写完之后发现我的逻辑其实有点复杂(先转为字符串进行分割,再分别转成数字进行计算),于是又找找看有没有其它的解决方法,因为我坚信我不可能是第一个遇到这种问题的人,于是很快发现了另一篇博客(能够解决此问题的一篇博客),完全解决了这个问题,即用到一个库:decimal,只保留整数就是 Decimal("1."),保留1位小数就是 Decimal(".1"),2位小数就是 Decimal(".01")Decimal(".89") 也是一样的,本质就是看你给的字符串中小数占了多少位而已】。

>>> from decimal import Decimal
>>> print(Decimal(1.5).quantize(Decimal("1."), rounding="ROUND_HALF_UP"))
2
>>> print(Decimal(2.5).quantize(Decimal("1."), rounding="ROUND_HALF_UP"))
3

3. 总结

解决方法,使用第三方库函数,格式是:Decimal(要进行四舍五入的数字).quantize(Decimal("保留多少位小数"), rounding="ROUND_HALF_UP")

>>> from decimal import Decimal
>>> num = 1.5
>>> print(Decimal(num).quantize(Decimal("1."), rounding="ROUND_HALF_UP"))
2

那么回到文章开头提出的问题,round为什么不能进行四舍五入呢? 其实round本质就是四舍五入,但是由于我们的计算机存储数字的精度有问题,才导致了这种情况发生:

>>> from decimal import Decimal
>>> print(Decimal(1.535))
1.5349999999999999200639422269887290894985198974609375
>>> print(Decimal(1.725))
1.725000000000000088817841970012523233890533447265625

详见 python3 小数位的四舍五入(用两种方法解决round 遇5不进),文中给出了两种解决方法。

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

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

相关文章

基于VMware安装Linux虚拟机

1.准备Linux环境 首先&#xff0c;我们要准备一个Linux的系统&#xff0c;成本最低的方式就是在本地安装一台虚拟机。为了统一学习环境&#xff0c;不管是使用MacOS还是Windows系统的同学&#xff0c;都建议安装一台虚拟机。 windows采用VMware&#xff0c;Mac则采用Fusion …

使用Spring Boot编写的小项目

加法计算器 前端代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…

若依跳转(新增)页面,在菜单中不显示的页面

在router.js文件中 跳转方式 this.$router.push(/monitor/b/b)

有限元之有限元法的实现

目录 一、单元刚度矩阵及单元荷载 二、总刚度矩阵及总荷载的合成 三、边界条件处理 四、算例实现 4.1 C代码 4.2 计算结果 五、结论 前三节我们介绍了有限元的基本概念、变分理论及有限元空间的构造&#xff0c;本节我们探讨如何实现有限元法。我们继续以二维椭圆型方程…

以太坊现货ETF获批:引发ETH价格暴涨,市场热议达到高潮

2024年5月24日&#xff0c;北京时间&#xff0c;以太坊现货ETF正式获得美国证券交易委员会&#xff08;SEC&#xff09;的批准&#xff0c;成为继比特币之后&#xff0c;美国主权政府承认的又一加密货币基金产品。这一意外的利好消息引发了加密货币市场的狂欢&#xff0c;以太坊…

JavaWeb开发 2.Web开发 Web前端开发 ①介绍

内心一旦平静&#xff0c;外界便鸦雀无声 —— 24.5.27 一、初识Web前端 网页有哪些部分组成? 文字、图片、音频、视频、超链接 ...网页&#xff0c;背后的本质是什么? 前端代码前端的代码是如何转换成用户眼中的网页的? 通过浏览器转化(解析和渲染)成用户看…

dx11硬件解码传递给opencl并行处理

directx11 解码 使用ffmpeg进行directx11 解码 将解码后的NV12格式数据从D3D11 Texture中通过OpenCL处理需要经过几个步骤&#xff1a;首先&#xff0c;确保D3D11 Texture正确设置并与OpenCL上下文关联&#xff1b;然后&#xff0c;将NV12数据分两个步骤处理&#xff08;Y平面…

调试面对面翻译小程序

调试面对面翻译小程序 文章目录 调试面对面翻译小程序预览1.拉取项目2.在微信开发者工具打开使用 微信版本要求微信同声传译插件支持功能 此demo用于学习 预览 1.拉取项目 git clone https://github.com/Tencent/Face2FaceTranslator或者&#xff08;加速镜像&#xff09; git …

Warning: Each child in a list should have a unique “key“ prop.

问题描述&#xff1a; 使用ProTable的时候&#xff0c;报错如下 原因分析&#xff1a; 根据报错内容可以分析出&#xff0c;表格数据缺少唯一key&#xff0c; <PaginationTablecolumns{columns}pagination{{pageSize: 10,current: 1,showSizeChanger: true,showQuickJum…

kafka 可以脱离 zookeeper 单独使用吗?为什么?

Kafka是一个分布式的流式处理平台&#xff0c;它依赖于Zookeeper来管理集群元数据、选举Leader以及故障恢复。在Kafka集群中&#xff0c;Zookeeper负责保存和维护分布式系统的信息。 虽然理论上可以将Kafka与Zookeeper分开&#xff0c;但实际上&#xff0c;Kafka在设计时就与Z…

JavaScript中的相等操作符(== vs ===)选择指南

在使用JavaScript进行比较时,我们经常会遇到相等操作符 == 和严格相等操作符 ===。本文将深入探讨这两者之间的区别,并说明在何种情况下应使用 === 而不是 ==。 相等操作符(==) 相等操作符 == 会在进行比较之前对其两个操作数进行必要的类型转换。这意味着即使两个操作数…

网络安全行为可控定义以及表现内容简述

在数字化快速发展的今天&#xff0c;网络安全已成为国家和企业不可或缺的防线。据统计&#xff0c;网络攻击事件频发&#xff0c;给全球经济带来了巨大损失。因此&#xff0c;确保网络安全行为可控显得尤为重要。今天我们来聊聊网络安全行为可控定义以及表现内容。 网络安全行为…

摸鱼大数据——Hive表操作——分区表

1、介绍 特点: 分区表会在HDFS上产生目录。查询数据的时候使用分区字段筛选数据&#xff0c;可以避免全表扫描&#xff0c;从而提升查询效率 注意: 如果是分区表&#xff0c;在查询数据的时候&#xff0c;如果没有使用分区字段&#xff0c;它回去进行全表扫描&#xff0c;会降低…

说一下 ACID 是什么?

ACID 是数据库事务的四个特性的首字母缩写&#xff0c;包括原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09;。 原子性&#xff08;Atomicity&…

什么是NAND Flash ECC?

在存储芯片行业&#xff0c;数据完整性和可靠性是至关重要的。为了确保数据的准确性和防止数据丢失&#xff0c;ECC&#xff08;错误校正码&#xff09;在NAND Flash存储中扮演了关键角色。MK米客方德将为您解答NAND Flash ECC的基本概念、工作原理及其在实际应用中的重要性。 …

重绘和重排

重绘&#xff08;Repaint&#xff09;和重排&#xff08;Reflow&#xff09;是与网页渲染和布局密切相关的两个概念。以下是关于这两个概念的详细解释&#xff1a; 重绘&#xff08;Repaint&#xff09; 定义&#xff1a; 当一个元素的外观发生改变&#xff0c;但没有改变布…

C#【进阶】俄罗斯方块

俄罗斯方块 文章目录 Test1_场景切换相关BeginScene.csBegionOrEndScene.csEndScene.csGame.csGameScene.csISceneUpdate.cs Test2_绘制对象基类和枚举信息DrawObject.csIDraw.csPosition.cs Test3_地图相关Map.cs Test4_坐标信息类BlockInfo.cs Test5_板砖工人类BlockWorker.…

数据库中字符串相加需要换行

数据库中字符串相加需要换行&#xff0c;这个需求在现在项目中很常见&#xff0c;特别是备注内容的追加&#xff0c;因此把Oracle/SQLServer/MySQL这几种数据库的使用进行简单的总结一下 1、本文内容 Oracle中实现字符串相加需要换行SQLServer中实现字符串相加需要换行MySQL中…

VMware的网络不通?这一篇给你一定的参考.虚拟机网络配置

如果你的虚拟机莫名其妙ping不通网络了&#xff0c;可以参考一下我的配置。这不是一篇教程&#xff0c;你可以核对一下自己的bug。 虚拟网络配置器中&#xff1a; 使用管理员权限更改设置&#xff0c;会跳出来vmnet0 桥接、仅主机和NAT都必须要有 vment0&#xff1a; vmnet1:…

【乐吾乐3D可视化组态编辑器】相机与视角

系统默认的相机为环绕旋转相机&#xff0c;它可以环绕一个中心点做上下左右的旋转&#xff0c;来从不同角度观察场景。当然&#xff0c;您也可以把一些特定角度的信息保存下来&#xff0c;在系统中我们把这个信息称作视角。通过交互中的切换视角动作&#xff0c;您就可以实现把…