解决Python中的modf()函数取小数部分不准确问题


Posted in Python onMay 28, 2021

使用math.modf()对一个浮点数进行拆分时经常会遇到如下情况

如下

import math
print(math.modf(2.4)) # 输出 (0.3999999999999999, 2.0)

我们会发现对2.4进行拆分得到的小数并不是0.4,这是因为什么呢?

这是因为计算机采用的是二进制代码,而二进制代码由于计算上的误差无法准确表示某些十进制数的小数部分。

下面我们具体来讲一下。

我们知道一个十进制数转化为二进制数需要分为两部分进行计算:整数部分和小数部分。

整数部分采用“除二取余法”。将这个整数除以2,得到它的余数,然后将商再除以3,直到商为0为止,并将各个得到的余数按照相反的顺序进行排列。

小数部分采用“乘2取整法”,将这个小数乘2,将新得到的数的整数部分取出,再用2乘余下的小数部分,如此往复直到乘积中的小数部分为0或者达到要求的精度为止。并将取出的整数部分按照取出的先后顺序从前到后排列。

123/2=61...1
 61/2=30...1
 30/2=15...0
 15/2=7...1
 7/2=3...1
 3/2=1...1
 1/2=0...1
 (123)10=(1111011)2
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1
0.2*2=0.4...0
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1
(0.4)10=(0.011001100110011001100110...)2
(123.4)2=(1111011.011001100110011...)2

十进制的0.4转化为二进制时会出现重复循环“0110”的情况,但是目前计算机存储浮点数是按照电器和电子工程师协会的标准(IEEE754浮点数存储格式标准)来进行存储的。

IEEE规定单精度浮点最多存储32位(4个字节):

31位是符号位。1表示该数为负,0为正

30~23是指数位(-128-127)

22~0是尾数位,尾数的编码一般是源码和补码

IEEE标准从逻辑上用三元组{S,E,M}表示一个数,如图所示:

解决Python中的modf()函数取小数部分不准确问题

也就是说上面将0.4转换出的二进制代码,我们只能存储23位,即使数据类型为double,也只能存储52位,这样大家便能看出问题出现的原因了。23位的数据显然无法完整表示0.4的二进制数据,于是误差产生了。

那所有的十进制小数都无法完整表示吗?不是的,只要小数部分乘上2最终小数部分能够得到0就不会出现这种问题,比如0.5,0.75。

import math
print(math.modf(1.5))  # 输出 (0.5,1.0)
0.5*2=1...1
(0.5)10=(0.1)2
0.75*2=1.5...1
0.5*2=1...1
(0.75)10=(0.11)2

补充:Python中“取整”的各种问题

一、初衷:

有时候我们分页展示数据的时候,需要计算页数。一般都是向上取整,例如counts=205 pageCouts=20 ,pages= 11 页。

一般的除法只是取整数部分,达不到要求。

二、方法:

1、通用除法:

UP(A/B) = int((A+B-1)/B)

取临界值,计算下A+B-1的范围就OK.

2 、Python除法:

首先要说的是python中的除法运算,

当使用x/y形式进行除法运算时,那么会进行所谓的true除法,比如2.0/3的结果是 0.66666666666666663。

另外一种除法是采用x//y的形式(向下取整),那么这里采用的是所谓floor除法,即得到不大于结果的最大整数值,这个运算时与操作数无关的。比如2//3的结果是0,-2//3的结果是-1,-2.0//3的结果是-1.0。

在python 3.0中,x/y将只执行true除法,而与操作数无关;x//y则执行floor除法。

Python运算向上取整方法:(A+B-1)/B

3、Python match.ceil函数 np.ceil函数

ceil(x)函数是向上取整,即取大于等于x的最接近整数。

import math 
math.ceil(float(205)/20) 
import numpy as np
np.ceil(float(205)/20)

Python 向上取整的算法

1、一般使用floor除法 (np.floor()或者math.floor())

import numpy as np 
n = np.array([-1.7, -2.5, -0.2, 0.6, 1.2, 2.7, 11]) 
floor = np.floor(n)
print(floor)  # [ -2.  -3.  -1.   0.   1.   2.  11.]

2、一般除法/

A=100
B=16
c=100//16
(c=6)

3、round()四舍五入函数。

np.around 返回四舍五入后的值,可指定精度。

around(a, decimals=0, out=None)

a 输入数组

decimals 要舍入的小数位数。 默认值为0。 如果为负,整数将四舍五入到小数点左侧的位置

import numpy as np 
n = np.array([-0.746, 4.6, 9.4, 7.447, 10.455, 11.555])
 
around1 = np.around(n)
print(around1)  # [ -1.   5.   9.   7.  10.  12.]
 
around2 = np.around(n, decimals=1)
print(around2)  # [ -0.7   4.6   9.4   7.4  10.5  11.6]
 
around3 = np.around(n, decimals=-1)
print(around3)  # [ -0.   0.  10.  10.  10.  10.]

Python 分别取整的算法

math模块中的 modf()方法

将整数部分和小数部分分别取出,可以使用math模块中的 modf()方法

例如:

>>> math.modf(4.25)
(0.25, 4.0)
>>> math.modf(4.33)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 返回汉字的汉语拼音
Feb 27 Python
python端口扫描系统实现方法
Nov 19 Python
python使用mailbox打印电子邮件的方法
Apr 30 Python
python中import学习备忘笔记
Jan 24 Python
Python3 加密(hashlib和hmac)模块的实现
Nov 23 Python
Python实现绘制双柱状图并显示数值功能示例
Jun 23 Python
python爱心表白 每天都是浪漫七夕!
Aug 18 Python
Python多线程同步---文件读写控制方法
Feb 12 Python
Python箱型图处理离群点的例子
Dec 09 Python
python 使用多线程创建一个Buffer缓存器的实现思路
Jul 02 Python
浅析Python中字符串的intern机制
Oct 03 Python
Python打包为exe详细教程
May 18 Python
利用Python+OpenCV三步去除水印
python实现自定义日志的具体方法
May 28 #Python
python 爬取京东指定商品评论并进行情感分析
python b站视频下载的五种版本
May 27 #Python
教你怎么用python selenium实现自动化测试
Python Django框架介绍之模板标签及模板的继承
May 27 #Python
python 算法题——快乐数的多种解法
May 27 #Python
You might like
百度站点地图(百度sitemap)生成方法分享
2014/01/09 PHP
php隐藏实际地址的文件下载方法
2015/04/18 PHP
PHP后期静态绑定之self::限制实例分析
2018/12/21 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
TNC vs BOOM BO3 第三场2.13
2021/03/10 DOTA
node.js中的http.response.setHeader方法使用说明
2014/12/14 Javascript
常用的JS验证和函数汇总
2014/12/23 Javascript
详解js中构造流程图的核心技术JsPlumb(2)
2015/12/08 Javascript
js 能实现监听F5页面刷新子iframe 而父页面不刷新的方法
2016/11/09 Javascript
浅析script标签中的defer与async属性
2016/11/30 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
2017/01/11 Javascript
JS去除字符串最后的逗号实例分析【四种方法】
2019/06/20 Javascript
浅谈layui 数据表格前后台传值的问题
2019/09/12 Javascript
js生成1到100的随机数最简单的实现方法
2020/02/07 Javascript
[01:23:59]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 VP vs Secret
2018/04/03 DOTA
python生成圆形图片的方法
2020/03/25 Python
python 给DataFrame增加index行名和columns列名的实现方法
2018/06/08 Python
利用arcgis的python读取要素的X,Y方法
2018/12/22 Python
用Python实现大文本文件切割的方法
2019/01/12 Python
python for 循环获取index索引的方法
2019/02/01 Python
python之生产者消费者模型实现详解
2019/07/27 Python
python中几种自动微分库解析
2019/08/29 Python
Python 元组拆包示例(Tuple Unpacking)
2019/12/24 Python
python实现ip地址的包含关系判断
2020/02/07 Python
使用TFRecord存取多个数据案例
2020/02/17 Python
如何把外网python虚拟环境迁移到内网
2020/05/18 Python
Python将字典转换为XML的方法
2020/08/01 Python
Ubuntu 20.04安装Pycharm2020.2及锁定到任务栏的问题(小白级操作)
2020/10/29 Python
如何利用python生成MD5并去重
2020/12/07 Python
结合 CSS3 transition transform 实现简单的跑马灯效果的示例
2018/02/07 HTML / CSS
美国家用和厨房电器销售网站:Appliances Connection
2020/01/24 全球购物
Java如何读取CLOB字段
2013/10/10 面试题
2014党的群众路线教育实践活动总结材料
2014/10/31 职场文书
2014年民警工作总结
2014/11/25 职场文书
MySQL数据库中varchar类型的数字比较大小的方法
2021/11/17 MySQL
面试提问mysql一张表到底能存多少数据
2022/03/13 MySQL