pythonfloat转int丢数据_【⼩思考】Python的float转换精度损
失所想到的
⾸先,为啥会要讨论这个问题。
我得为昨天拖了⼩组后腿深表歉意。其实程序逻辑很快就理通了的,但⾃⼰总是会因为各种各样的⼩问题束缚⼿脚,看接下来这个图⽚:
稍微有数据敏感性的同学就能看出,中间这么⼀⼤堆⼜是0000⼜是999还是这么多位的⼩数,⼀看就是异常数据。这块数据的产⽣,源于代码⾥对两个字符串做了float转换并相减,导致出现了这种数据异常的错误。那么问题来了,1.这种异常是如何产⽣的?2.有哪些⽅法可以解决这种问题呢?3.编程中间还有哪些与这个问题相关的注意事项呢?
第⼀部分:这种异常是如何产⽣的呢?
我们先来看演⽰:
看来,直接输出float型数据,以及对字符串进⾏的float转换,本⾝并没有什么问题,那么为什么浮点数相减就会出现这个可恶的⼩尾巴呢?我们有必要从计算机本⾝数字加减的机制进⾏探究。有学习过《计算机组成原理》等基本课程、哪怕只是简单了解计算机内部运⾏机制的同学都明⽩,计算机内部的加减乘除都是要把数字转化成为⼆进制实现的。那么,我们此处的浮点数,也要转换为⼆进制,才能进⾏计算。Python内浮点数是⽤机器上浮点数的本机双精度(64 bit)表⽰的。提供⼤约17位的精度和范围从-308到308的指数。和C语⾔⾥⾯的double类型相同【可参考C语⾔double类型的解释】。
我们来看⼀个简单的例⼦。⼗进制1.1转换成⼆进制是什么数?⼗进制整数部分转化成⼆进制,⽤短除法处以2倒序取余。⼩数部分转化为⼆进制是⽤乘法乘2正序取整。见下⾯⼀个浮点数转⼆进制数的例⼦。
1.10整数部分就是1,转换成⼆进制1(这⾥整数转⼆进制不再赘述)
⼩数部分:0.1
0.1*2=0.2取整数部分0,基数=0.2
0.2*2=0.4取整数部分0,基数=0.4
0.4*2=0.8取整数部分0,基数=0.8
编程先学c语言还是python0.8*2=1.6取整数部分1,基数=1.6-1=0.6
0.6*2=1.2取整数部分1,基数=1.2-1=0.2
0.2*2=0.4取整数部分0,基数=0.4
.
.
.
直⾄基数为0。1.1⽤⼆进制表⽰为:(后⾯表⽰省略)
关于之前的演⽰,相当于,因为3.4的存储,发⽣了精度损失(3.5不会,因为3.5的⼆进制是11.1,补码存储依然不会发⽣精度损失),所以在相减的时候,发⽣了⼀次精度损失,最后结果存储的时候,再次发⽣⼀次精度损失。所以,才会出现最后的⼩尾巴情况。
第⼆部分:有哪些⽅法可以解决这个问题呢?
解决这个问题?不存在的,除⾮是提⾼精度——让计算机内能够完整的存储数字的⼆进制(⼆进制补码)
表⽰,否则的话,只要有精度损失,就指不定什么时候会冒出来⼩尾巴。我们追求的解决,⾃然也是从提⾼精度,和“表⾯看起来正确”这两条道路去追求。
提⾼精度——Python本⾝⾃带的float已经是可⽀持浮点数的最⾼精度形式。当然,这个肯定是不能阻挡我们对更⾼精度的要求,这⾥可以⾃⼰实现⾼精度的数据形式,也可以使⽤Python扩展模块:Decimal。使⽤Decimal本⾝需要导⼊decimal包,初始化decimal数据可以使⽤整型数据和字符串,⽽不能使⽤float型数据,正如之前我们所说的那样,某些浮点数存储会发⽣精度损失——这意味着float本⾝就不够精确。
当然,还有很多抖机灵的⽅法,⽐如说结果转换成字符串然后再截取?!
你可能体会不到,这个是⼀种针对数据波动范围相对确定,相当实⽤的⽅法——虽然应该没有任何⼀个脑⼦正常的程序员会推崇这种⽅法。这种⽅法就是追求的“表⾯上看起来正确”,你看,最后的显⽰出来的结果不就是-0.1么?
⾃然,还有print的%精度控制,这⾥就不赘述。⽽且也不想详述这个,毕竟这个惊为天⼈的字符串截取⽅法,都还是对字符串进⾏了处理,⽽%精度控制只是显⽰的时候做了处理,可真是够“表⾯”的。
不得不说,也是受这种⽅法的启发,本⼈使⽤的⽅法,是利⽤Python int转换“舍去⼩数点后所有数字”的特点,把原浮点数乘以需要保留精度的位数,然后转换成整数,再除回去,这样就形成了“表⾯正
确”的数据,效果不要太好。
总结⼀下!解决这个精度损失带来的“恶魔⼩尾巴”问题,我们⼤体上有提⾼数据格式精度和只追求最终显⽰改变两⼤思路。
提⾼数据格式精度:使⽤扩展包decimal
只追求最终显⽰改变:printf %精度控制 ,字符串截取指定位数,先移动⼩数点、转换成整型舍去末尾、再把⼩数点移动回来。等⽅法。
第三部分:编程中间还有哪些和这个问题相关的注意事项呢?
这个⼩尾巴让我可谓⼀开始是焦头烂额,也严重耽误了⼩组研究进度。通过我们之前的探究,可以发
现,浮点数本⾝表⽰由于受计算机限制,经常是不精确的。所以,⽇常数据中,最好不要⽤浮点数。
可能有些⼈觉得精度损失⼀些没有什么,然⽽浮点数的精度损失关键时候可不只只是精度损失,甚⾄会影响流程控制!浮点数不只有Python⾥⾯有,咱们⽤更加基本的C++来说明这个问题:
当精度损失已经让程序的⾛向开始不符合逻辑的时候,你还会轻视这个问题么?
这⾥给⼴⼤同仁们分享⼀篇专门讲解浮点数的⽂章,深⼊了解,真的有很多可圈可点之处!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论