【Python】浮点数计算时的不准确性以及如何进行精确计算

浮点数一个普遍的问题就是在计算机的世界中,浮点数并不能准确地表示十进制。并且,即便是最简单的数学运算,也会带来不可控制的后果。因为,在计算机的世界中只认识0与1
因为在计算机里面,小数是不精确的,例如1.115在计算机中实际上是1.1149999999999999911182,所以当你对这个小数精确到小数点后两位的时候,实际上小数点后第三位是4,所以四舍五入,因此结果为1.11。
这种说法,对了一半。因为并不是所有的小数在计算机中都是不精确的。例如0.125这个小数在计算机中就是精确的,它就是0.125,没有省略后面的值,没有近似,它确确实实就是0.125。
但是如果我们在Python中把0.125精确到小数点后两位,那么它的就会变成0.12,为什么在这里四舍了?
还有更奇怪的,另一个在计算机里面能够精确表示的小数0.375,我们来看看精确到小数点后两位是多少:,为什么这里又五入了?因为在Python 3里面,round对小数的精确度采用了四舍六入五成双的方式。
如果你写过大学物理的实验报告,那么你应该会记得老师讲过,直接使用四舍五入,最后的结果可能会偏高。所以需要使用奇进偶舍的处理方法。
例如对于一个小数a.bcd,需要精确到小数点后两位,那么就要看小数点后第三位:   如果d小于5,直接舍去;如果d大于5,直接进位;
如果d等于5:d后面没有数据,且c为偶数,那么不进位,保留c。d后面没有数据,且c为奇数,那么进位,c变成(c + 1)
python中的decimal模块可以解决上面的烦恼 
decimal模块中,可以通过整数,字符串或原则构建decimal.Decimal对象。如果是浮点数,特别注意因为浮点数本身存在误差,需要先将浮点数转化为字符串。
当然精度提升的同时,肯定带来的是性能的损失。在对数据要求特别精确的场合(例如财务结算),这些性能的损失是值得的。
但是如果是大规模的科学计算,就需要考虑运行效率了。毕竟原生的float比Decimal对象肯定是要快很多的。

Python提供了decimal模块用于十进制数学计算,它具有以下特点:
1.提供十进制数据类型,并且存储为十进制数序列;
2.有界精度:用于存储数字的位数是固定的,可以通过decimal.getcontext().prec=x 来设定,不同的数字可以有不同的精度
3.浮点:十进制小数点的位置不固定(但位数是固定的)

python decimal.quantize()参数rounding的decimal文档里面的解释:
ROUND_CEILING (towards Infinity),
ROUND_DOWN (towards zero),
ROUND_FLOOR (towards -Infinity),
ROUND_HALF_DOWN (to nearest with ties going towards zero),
ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),
ROUND_HALF_UP (to nearest with ties going away from zero), or
ROUND_UP (away from zero).
ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)

下面通过具体代码理解每个参数

# -*- coding: utf-8 -*-
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#作者:cacho_37967865
#博客:https://blog.csdn.net/sinat_37967865
#文件:dealFloat.py
#日期:2019-08-01
#备注:python使用浮点类型float计算后,数值可能不对,这时候需要使用decimal模块
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''from decimal import Decimal,getcontext
from decimal import ROUND_UP,ROUND_DOWN,ROUND_HALF_UP,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_05UP,ROUND_CEILING ,ROUND_FLOORx = 4.20
y = 2.10
a = 1.20
b = 2.30
d = 195.00def float_info():# a.bcd ,精确2位小数点i = 1.115  # 在计算机中实际上是1.1149999999999999911182      四舍五入:1.11j = 0.125  # d后面没有数据,且c为偶数,那么不进位,保留c        四舍五入:0.12l = 0.1251 # d后面有数据,c变成(c + 1)                       四舍五入:0.13k = 0.375  # d后面没有数据,且c为奇数,那么进位,c变成(c + 1)   四舍五入:0.38print('四舍五入:',round(i,2))print('四舍五入:',round(j, 2))print('四舍五入:',round(l, 2))print('四舍五入:',round(k, 2))def decimal_info():# a.bcd ,精确2位小数点 默认进位方式i = 1.115  # 在计算机中实际上是1.1149999999999999911182      四舍五入:1.11j = 0.125  # d后面没有数据,且c为偶数,那么不进位,保留c        四舍五入:0.12l = 0.1251 # d后面有数据,c变成(c + 1)                       四舍五入:0.13k = 0.375  # d后面没有数据,且c为奇数,那么进位,c变成(c + 1)   四舍五入:0.38print('浮点型数据不精确:',Decimal(i))print('浮点型数据也可能精确:', Decimal(j))print('传入的是字符串默认方式四舍五入:', Decimal(str(i)).quantize(Decimal('0.00')))   # 1.12print('传入的是浮点型默认方式四舍五入:',Decimal(i).quantize(Decimal('0.00')))         # 1.11print('传入的是浮点型默认方式四舍五入:',Decimal(j).quantize(Decimal('0.00')))print('传入的是浮点型默认方式四舍五入:',Decimal(l).quantize(Decimal('0.00')))print('传入的是浮点型默认方式四舍五入:',Decimal(k).quantize(Decimal('0.00')))# 最好传入字符串print('传入的是字符串真实四舍五入:', Decimal(str(i)).quantize(Decimal('0.00'), ROUND_HALF_UP))print('传入的是字符串真实四舍五入:', Decimal(str(j)).quantize(Decimal('0.00'), ROUND_HALF_UP))print('传入的是字符串真实四舍五入:', Decimal(str(l)).quantize(Decimal('0.00'), ROUND_HALF_UP))print('传入的是字符串真实四舍五入:', Decimal(str(k)).quantize(Decimal('0.00'),ROUND_HALF_UP))print('传入的是字符串向上取值:', Decimal('0.121').quantize(Decimal('0.00'), ROUND_UP))              # 向上入 0.13print('传入的是字符串向下取值:', Decimal('0.129').quantize(Decimal('0.00'), ROUND_DOWN))            # 向下舍 0.12print('传入的是字符串向上四舍五入:', Decimal('0.125').quantize(Decimal('0.00'), ROUND_HALF_UP))      # 最后一位5向上入 0.13print('传入的是字符串向下四舍五入:', Decimal('0.125').quantize(Decimal('0.00'), ROUND_HALF_DOWN))    # 最后一位5向下舍 0.12print('传入的是字符串默认方式四舍五入:', Decimal('0.125').quantize(Decimal('0.00'), ROUND_HALF_EVEN))  # 默认四舍五入方式 0.12     quansize的默认设置值print('传入的是字符串默认方式四舍五入:', Decimal('0.375').quantize(Decimal('0.00'), ROUND_HALF_EVEN))    # 默认四舍五入方式 0.38print('传入的是字符串精确位数字为5入:', Decimal('5.351').quantize(Decimal('0.00'), ROUND_05UP))       # 精确的最后一位为0或者5向上入,否者向下舍5.36print('传入的是字符串精确位数字为0入:', Decimal('5.301').quantize(Decimal('0.00'), ROUND_05UP))       # 精确的最后一位为0或者5向上入,否者向下舍5.31print('传入的是字符串精确位数字非0和5舍:', Decimal('5.399').quantize(Decimal('0.00'), ROUND_05UP))       # 精确的最后一位为0或者5向上入,否者向下舍5.39print('传入的是字符串正数时与ROUND_UP一致:', Decimal('5.391').quantize(Decimal('0.00'), ROUND_CEILING))     # 5.40print('传入的是字符串正数时与ROUND_DOWN一致:', Decimal('5.399').quantize(Decimal('0.00'), ROUND_FLOOR))     # 5.39print('传入的是字符串负数时与ROUND_DOWN一致:', Decimal('-5.399').quantize(Decimal('0.00'), ROUND_CEILING))    # -5.39  趋近于正无穷print('传入的是字符串负数时与ROUND_UP一致:', Decimal('-5.399').quantize(Decimal('0.00'), ROUND_FLOOR))       # -5.40  趋近于负无穷print('传入的是字符串与正负无关,最后一位始终进:', Decimal('-5.399').quantize(Decimal('0.00'), ROUND_UP))def float_deal():z = x + y                # 6.300000000000001print(z)if z == 6.30:print("z计算正确")else:print("z计算错误")c = a + bprint(c)if c == 3.5:print("c计算正确")else:print("c计算错误")e = round(195.00 / 24,2)print(e)if e == 8.13:print("e四舍五入正确")else:print("e四舍五入错误")def decimal_deal():getcontext().prec = 3                     # 设置精确值,只针对计算时无法除净时z = Decimal(str(x)) + Decimal(str(y))print(type(z),z)e = Decimal('195.00') / Decimal('24')print(e)if __name__ == '__main__':float_info()decimal_info()#float_deal()#decimal_deal()

 

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

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

相关文章

echarts自定义showlading()样式和文本

1、首先引入echarts.js 2、在页面定义自己的echarts变量 var myChart echarts.init(document.getElementById(main)); 3、自定义showLoading()样式 myChart.showLoading(default, {text:统计中,请稍候...,maskColor: #404a59,textColor: #fff,}); text:文本内…

【视频】视频基本参数介绍

视频(Video)泛指将一系列静态影像以电信号的方式加以捕捉、纪录、处理、储存、传送与重现的各种技术。 连续的图像变化每秒超过24帧(frame)画面以上时,根据视觉暂留原理,人眼无法辨别单幅的静态画面&#x…

测试人员做到这几点,线上80%的BUG将落入你手,企业将避免重大风险

BUG事故给敲了很大的警钟,也给公司带来重大损失,作为测试人员,我们如何提现发现线上BUG并及时解决,避免落入用户手中,给企业带来无法挽回的损失。 案例1: 1月20日凌晨,拼多多App因技术漏洞&am…

Django与jQuery通信;Django前后端传值

window.onloadfunction(){var user_info{{user_info|default_if_none:0}};if(user_info0){alert("您好没有登录!");window.location.href"/login"; //跳转到登录界面} } 参考自:https://blog.csdn.net/PlusChang/article/details/7…

【Python】pysnooper模块对代码进行调试

一般情况下,在编写Python代码时,如果想弄清楚为什么Python代码没有按照预期执行的原因,比如你想知道哪些是正在运行,哪些没有运行,以及局部变量的值是什么... 通常我们会使用包含断点和观察模式等功能成熟的调试器&…

解决$ is not define

今天写js的时候,发现怎么也没有效果。然后我前端调试的时候报这样的错 $ is not define 这个错误我以前也出现过。所以就这个错误的解决,我来总结一下。 1.首先,"$"这个符号是在jquery中定义的。所以你要看一下,你有没…

模拟导入系统通讯录5000+手机号 校验大量数据处理

模拟导入系统通讯录5000手机号 校验大量数据处理 之前再测试一个导入手机通讯录系统时,随机抽了几个人的手机进行了测试,都导入显示正常 当公司BD进行项目试用时,导入通讯录一直处于下图加载中 1、于是进行抓包查看日志进行定位&#xff0c…

【股票】股票交易的手续费介绍以及计算

股票交易手续费是进行股票交易时所支付的手续费。委托买卖的手续费分“阶段式”和“跟价式”。(1)阶段式。根据股票价格和交易股数收取手续费。(2)跟价式。根据股票的交易金额收取手续费,目前世界上多采用跟价式。 我国目前主要是证券公司收取佣金和国家收取的印花税…

python3下使用cv2.imwrite存储带有中文路径图片或者绝对路径图片

由于imwrite前使用编码在python3中已经不适用,可用imencode代替,以下代码是从视频中获取第2帧保存在中文文件夹下的实例: 1 2 3 4 5 cap cv2.VideoCapture("***.mp4") cap.set(cv2.CAP_PROP_POS_FRAMES, 2) ret, framecap.read…

浅析python类继承(一)

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父…

【Python】常用的数据类型介绍以及它们之间相互转化

在学习一门语言的过程中,首先肯定就是要先接触到它所拥有的数据类型,Python拥有多种主要的数据类型,下面介绍一下下面9种数据类型,以及一些数据类型之间的转化。 目录 1、字符串 2、布尔类型 3、整数 4、浮点数 5、数字 6、列表 7…

django select option拼接时value中空格后的内容被截断

$new $("<option value"List[i] ">"List[i]"</option>" ); $("#project").append( $new ); 此时若value中的字符串有空格&#xff0c;则会被空格截断 解决方法&#xff1a; $new $("<option value"List…

Monkey随机性能压测初探(一)

Monkey介绍 Monkey程序由Android系统自带&#xff0c;是Android SDK提供的一个命令行工具&#xff0c; 可运行Android模拟器和实体设备上。Monkey会发送伪随机的用户事件流&#xff0c;通过Monkey程序模拟用户触摸屏幕、滑动、 按键等操作来对程序进行压力测试&#xff0c;检测…

【Java】使用前准备工作配置环境变量

我们要使用java前&#xff0c;必须先安装JDK并且配置相关的环境变量&#xff0c;如果我们未配置环境变量&#xff0c;那么我们在cmd命令中&#xff0c;输入javac&#xff0c;会提示“javac”不是内部或外部命令&#xff0c;这里主要介绍如何配置jdk的环境变量。 JDK官网下载&a…

怎么在html的img src=src的值这里调用js方法或变量获取图片地址

<html> <head>参考自 </head> <body> <img src"?" id"img"> </body> <script language"javascript"> var adres"图片地址"; document.getElementById(img).src adres; </sc…

Jmeter性能测试工具Timer定时器详解

jmeter提供了很多元件&#xff0c;帮助我们更好的完成各种场景的性能测试&#xff0c;其中&#xff0c;定时器&#xff08;timer&#xff09;是很重要的一个元件&#xff0c;jemter提供了9种定时器&#xff0c;下面一一介绍&#xff1a; 一、定时器的作用域 1、定时器是在每个…

js/jq进行日期格式化为:yyyy-MM-dd 如2017-05-08

设置日期为yyyy-MM-dd,代码如下&#xff1a; function setDefaultDate() {var mydate new Date();var month myDate.getMonth() 1;var day myDate.getDate();month (month.toString().length 1) ? ("0" month) : month;day (day.toString().length 1) ? (…

【Maven】Java项目管理工具

一、为什么要Maven 在开发中经常需要依赖第三方的包&#xff0c;包与包之间存在依赖关系&#xff0c;版本间还有兼容性问题&#xff0c;有时还里要将旧的包升级或降级&#xff0c;当项目复杂到一定程度时包管理变得非常重要。 Maven是当前最受欢迎的Java项目管理构建自动化综合…

fiddler抓包工具配置详解

没有解决不了的问题&#xff0c;只是没有找到合适的方法 fiddler官网 https://www.progress.com/ 官网下载fiddler https://www.telerik.com/download/fiddler/fiddler4 fiddler插件下载 https://www.telerik.com/fiddler/add-ons 最近看到很多人都在问的一个问题&#xff0…

js 截取字符串

本文为大家介绍三种 js 截取字符串的方法&#xff1a; substring() 方法&#xff1b;substr() 方法&#xff1b;slice() 方法&#xff1b; 方法1&#xff1a;substring() 方法 string.substring(from, to) 方法从 from 位置截取到 to 位置&#xff0c;to 可选&#xff0c;没有…