python 如何将浮点数尾部无效0去掉和无效的‘.’号

方法一:

a = 12.12300 #结果要求为12.123
b = 12.00 #结果为12
c = 200.12000 #结果为200.12
d = 200.0 #结果为200

print 'a==>' ,[ str (a), int (a)][ int (a) = = a]
print 'b==>' ,[ str (b), int (b)][ int (b) = = b]
print 'c==>' ,[ str (c), int (c)][ int (c) = = c]
print 'd==>' ,[ str (d), int (d)][ int (d) = = d]

方法二:

for i in [ 12.12300 , 12.00 , 200.12000 , 200.0 ]:
 print ( '{:g}' . format (i))

补充:Python 只有1%的程序员搞懂过浮点数陷阱

稍有标题党味道,但内容纯干货,先从一个例子说起

>>> 0.1+0.2==0.3
False

当你第一次看到这个结果时可能会非常惊讶,原来还有个这么大的bug,再来看看表达式 0.1+0.2 到底等于多少?

>>> 0.1+0.2
0.30000000000000004

完全超出我们的想象。那么这个操作在计算机里面到底发生了什么事情?

我们还是回到二进制。

首先,需要明确一点,在计算机中无论是整数、浮点数、还是字符串最终都是用二进制来表示的。

整数的二进制表示法

整数 9 在计算机中二进制表示是: 1001 ,怎么得来的?

用十进制整数整除以2,得到商和余数,该余数就是二进制数的最低位,然后继续用商整除以2,得到新的商和余数,以此类推,直到商等于0,由所有余数倒排组成了该整数的二进制表现形式。用代码表示是:

>>> n = 9
>>> while n >0:
  n,e = divmod(n, 2) # divmod返回n除以2的商和余数
  print(e)
1 # 低位
0
0
1 # 高位

二进制转化为十进制整数

我们知道,十进制用科学计算法可表示为:

123 = 1*10^2 + 2*10^1 + 3*10^0
= 100 + 20 + 3
= 123

同样的道理,如果是二进制数,可表示:

1001 = 1*2^3 + 0*2^2 +0*2^1 + 1*2^0
= 8+0+0+1
= 9

再来看浮点数

浮点数的二进制表示法

二进制小数和二进制整数没什么区别,都是由0和1组成,只是多了一个点,例如:101.11 就是一个二进制小数,对应的十进制数是:

101.11 = 1*2^2 + 0*2^1 + 1*2^0 + 1*2^-1 + 1* 2^-2
= 4 + 0 + 1 + 1/2 + 1/4
= 5 + 0.5 + 0.25
= 5.75

小数点左边用 2^n 表示,小数点右边的值用 2^-n来表示。

浮点数转换成二进制小数

十进制的浮点数转换成二进制小数的步骤:

小数点前面的整数部分按照十进制转二进制的方式操作

小数部分乘以2,取整数0或者1,剩下的小数继续乘2一直重复,直到小数部分为0或达到指定的精度为止

例如 2.25 转换成二进制小数,整数2转换为二进制是 10, 小数部分0.25转换二进制是:

0.25 * 2 = 0.5 整数为0,小数为0.5
0.5 * 2 = 1.0  整数为1,小数为0

所以 2.25 表示成二进制小数是 10.01 , 但并不是每一个浮点数都这么幸运最后乘2小数为0的,比如 0.2 转换成二进制是:

0.2*2 = 0.4 整数为0,小数为0.4
0.4*2 = 0.8 整数为0,小数为0.8
0.8*2 = 1.6 整数为1,小数为0.6
0.6*2 = 1.2 整数为1,小数为0.2
0.2*2 = 0.4 整数为0,小数为0.4
0.4*2 = 0.8 整数为0,小数为0.8
0.8*2 = 1.6 整数为1,小数为0.6
0.6*2 = 1.2 整数为1,小数为0.2

一直重复 ....

0.2 用二进制表示是 0.001100110011… ,你会发现 0.2 根本没法用二进制来精确表示。就像 1/3 无法用小数精确表示一样,只能取一个近似值。

如果把这个二进制小数 0.001100110011 转换回10进制是:

0.001100110011 = 1*2^-3 + 1* 2^-4 + 1* 2^-7 + 1* 2^-8 + 1* 2^-11 + 1* 2^-12
= 1/8 + 1/16 +1/128 + 1/256 + 1/2048 + 1/4096
= 0.199951171875

这只是一个接近 0.2 的数,精度越高就越靠近 0.2, 但永远不可能等于0.2。那么在计算机内部,浮点数到底怎么存储的呢?

根据国际标准IEEE 754,一个二进制浮点数 V 分为3部分,可以用下面这个公式来表示:

s表示符号位,当s=0,V为正数;

当s=1,V为负数

M表示有效数字, 1<=M<2

E表示指数位

例如十进制1.25,写成二进制是1.01,用该公式表示相当于 1.01×2^0。可以得出s=0,M=1.01,E=0。

IEEE 754规定

1、对于32位的浮点数,最高位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

2、对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M

3、M的第一位总是1,会被舍去,比如保存1.01的时候,实际上只保存小数点后面的01部分

4、E的真实值必须再减去一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

基于以上规则,我们可以对浮点数进行验证,可以用下面这个函数查看一个浮点数在计算机中实际存储的值:

import struct
def float_to_bits(f):
s = struct.pack('>f', f)
return struct.unpack('>l', s)[0]

>>>print(float_to_bits(0.2))
1045220557
print(bin(float_to_bits(0.2)))
0b111110010011001100110011001101

浮点数 0.2 实际存储的值是 1045220557,对应的二进制是 111110010011001100110011001101,转换成32位整数还要在前面补2个0,最后变成:

0 01111100 10011001100110011001101

最高位为0,所以表示正数,接着8位 01111100 是指数位E,对应整数是124,根据IEEE 754规定,E的真实值要减去127,所以E=-3,最后23为是M的值,因为前面省略了一位,所以M的真实值是:

1.10011001100110011001101

最后V的值就是:

1.10011001100110011001101*2^-3
=
0.00110011001100110011001101
=
1/8 + 1/16 +1/128 + 1/256 + 1/2048 + 1/4096 + ...
=
0.20000000298023224

它的实际值比 0.2 要大一点点,所以才看到了最开始的那一幕。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Python中关于浮点数的冷知识

    本周的PyCoder's Weekly 上分享了一篇小文章,它里面提到的冷知识很有意思,我稍作补充,分享给大家. 它提到的部分问题,读者们可以先思考下: 若两个元组相等,即 a==b 且 a is b,那么相同索引的元素(如 a[0] .b[0])是否必然相等呢? 若两个对象的 hash 结果相等,即 hash(a) == hash(b),那么它们是否必然相等呢? 答案当然都为否(不然就不叫冷知识了),大家可以先尝试回答一下,然后再往下看. -----思考分割线----- 好了,先来看看第一个问

  • Python浮点数四舍五入问题的分析与解决方法

    问题 昨天遇到一个问题,在 6.6045 保留三位小数时,使用 round() 函数进行计算,我们希望得到 6.605,然而: >>> round(6.6045, 3) 6.604 网上有人说,因为在计算机里面,小数是不精确的,例如 1.115 在计算机中实际上是 1.114999999999999991182,所以当你对这个小数精确到小数点后两位的时候,实际上小数点后第三位是 4,所以四舍五入,结果为 1.11. 这种说法,对了一半. 因为并不是所有的小数在计算机中都是不精确的.例如

  • Python3中的最大整数和最大浮点数实例

    Python中的最大整数 Python中可以通过sys模块来得到int的最大值. python2中使用的方法是 import sys max = sys.maxint print (max) python3中使用的方法是: import sys max = sys.maxsize print (max) Python中获得最大浮点数 方法一:使用sys模块 >>> import sys >>> sys.float_info sys.floatinfo(max=1.797

  • Python如何执行精确的浮点数运算

    问题 你需要对浮点数执行精确的计算操作,并且不希望有任何小误差的出现. 解决方案 浮点数的一个普遍问题是它们并不能精确的表示十进制数. 并且,即使是最简单的数学运算也会产生小的误差,比如: >>> a = 4.2 >>> b = 2.1 >>> a + b 6.300000000000001 >>> (a + b) == 6.3 False >>> 这些错误是由底层CPU和IEEE 754标准通过自己的浮点单位去执行

  • python 工具 字符串转numpy浮点数组的实现

    不同的数字之间使用 空格" ","$","*"等隔开,支持带小数点的字符串 NumArray=str2num(LineString,comment='#') 将字符串中的所有非Double类型的字符全部替换成空格 以'#'开头直至行尾的内容被清空 返回一维numpy.array数组 import numpy import scipy def str2num(LineString,comment='#'): from io import Strin

  • python 浮点数四舍五入需要注意的地方

    本文主要分享基于python的数据分析三方库pandas,numpy的一次爬坑经历,发现并分析了python语言对于浮点数精度处理不准确的问题,并在最后给出合理的解决方案.如果你也在用python处理数据,建议看一下,毕竟0.1的误差都可能造成比较大的影响. 问题出现 早上到了公司,领导发了几个文件过来,说这两天测试环境跑出来的数据,与实际情况有所出入,看看哪出的问题,尽快解决··· 开始排查 先对比数据,发现并不是所有的数据都出现问题,只有10%左右的数据有这个问题,说明应该不是逻辑上的问题,

  • python 如何将浮点数尾部无效0去掉和无效的‘.’号

    方法一: a = 12.12300 #结果要求为12.123 b = 12.00 #结果为12 c = 200.12000 #结果为200.12 d = 200.0 #结果为200 print 'a==>' ,[ str (a), int (a)][ int (a) = = a] print 'b==>' ,[ str (b), int (b)][ int (b) = = b] print 'c==>' ,[ str (c), int (c)][ int (c) = = c] print

  • Java去掉小数点后面无效0的方案与建议

    目录 一:需求 二:方案 2.1 正则匹配 2.2 BigDecimal 三:测试 四:建议 一:需求 当小数位很多的时候,小数位后面可能有一些多余的0并没有任何实际意义.所以在某些业务需求下可以去掉这些多余的0.例如:0.2000可以用0.2来表示. 二:方案 2.1 正则匹配 /** * 去掉给定字符串(小数)后面的无效0 * * @param value 小数的字符串表示 * @return 如果转换失败,返回null */ public String convertByPattern(S

  • python 移除字符串尾部的数字方法

    今天在下脚本的时候遇到一个问题,比如有这样的一个字符串 t = "book123456",想把尾部的数字全部去掉,只留下"book",自己用正则试了下,是实现了,但速度不是很快,于是问了一下同事,他给的解决的方法确实很简洁,也让自己长了知识点,如下: import string t.rstrip(string.digits) 这样就全部将数字移除了,顺便将string这个模块看了下文档,也有一定的收获. >>> import string >

  • Python中的浮点数原理与运算分析

    本文实例讲述了Python中的浮点数原理与运算.分享给大家供大家参考,具体如下: 先看一个违反直觉的例子: >>> s = 0. >>> for i in range(10): s += .1 >>> s 0.9999999999999999 # 错误被累加 再看一个更为普遍,直接影响判断逻辑的例子: >>> from math import sqrt >>> a = sqrt(2) >>> a*a

  • 使用Python去除小数点后面多余的0问题

    目录 Python去除小数点后面多余的0 Python去掉数字前面的0 Python去除小数点后面多余的0 最近在用Python 写导入数据的脚本.百度 必应搜了好多,都没有一个完美解决的. 在这里还是要吐槽一下百度对于这些真的很垃圾. 后来FQ谷歌了一下,第一个词条出来就找到办法了. 这里我搬过来整理一下,以及使用时候可能遇到的问题.希望对看到这篇文章的读者有用 首先引入头文件 from decimal import Decimal 举个例子 数字 100.2000 第一次 这么使用 Deci

  • python生成多个只含0,1元素的随机数组或列表的实例

    如下所示: >>> import numpy as np >>> myarray= np.random.randint(0,2,10)输出只含0,1元素的一维数组,长度为10 >>> myarray array([1, 1, 1, 0, 1, 0, 0, 1, 1, 0]) >>> myarray= np.random.randint(0,2,(3,10))输出只含0,1元素的3行10列数组 >>> myarray

  • Python实现的对本地host127.0.0.1主机进行扫描端口功能示例

    本文实例讲述了Python实现的对本地host127.0.0.1主机进行扫描端口功能.分享给大家供大家参考,具体如下: 前面一篇<Python IP端口扫描工具类>详细介绍了端口扫描功能,这里分析一下针对本地localhost端口扫描的方法. 具体代码如下: #!/usr/local/bin/python #-*- coding: UTF-8 -*- #端口扫描器 import socket import thread import time socket.setdefaulttimeout(

  • Python创建一个元素都为0的列表实例

    实现创建一个元素都为0的列表: l=10 lis=[0]*l lis 输出结果: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 以上这篇Python创建一个元素都为0的列表实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 浅析python 动态库m.so.1.0错误问题

    $ python -V python: error while loading shared libraries: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory ldd是列出动态库依赖关系: $ ldd /usr/local/bin/python3.6 linux-vdso.so.1 => (0x00007fffecbba000) libpython3.6m.so.1.0 => n

  • Java两种方法计算出阶乘尾部连续0的个数

    第一个方法是计算出阶乘然后计算字符串的0的个数. import java.util.Scanner; import java.math.BigDecimal; import java.text.DecimalFormat; public class jc{ public static void main(String args[]){ Scanner reader = new Scanner(System.in); DecimalFormat a = new DecimalFormat("#&q

随机推荐