python float精度处理

232 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

微信图片_20220815225525.jpg

一个简单的面试题:

>>>0.1+0.1+0.1

0.2

>>>0.1+0.1+0.1

0.30000000000000004

>>>0.1+0.1+0.1-0.3

5.551115123125783e-17

下面一个简单的例子:

a = 0.0

for i in range(10):

  print(a)
a+=0.1

结果: 打印0.1 连续相加10次,会显示不同的值,既是精度损失造成的.

另外一个问题:(精度控制)

关于小数和取整->高精度---低精度 round()

1. 不指定小数点位数, 即取整数, 四舍五入: (取到哪一位的后面一位, 若遇到.5 奇进偶不进)

round(2.3)   -2.0

round(2.6)   -3.0

round(2.5)   -3.0

round(1.5)   -2.0

2. 指定小数点位数, 即有小数位, 四舍五入: (取到哪一位的后面一位, 若遇到.5 偶进奇不进)

round(2.635,2)  -2.63

round(2.645,2)  -2.65

round(2.655,2)  -2.65

round(2.665,2)  -2.67

round(2.675,2)  -2.67

3. math模块的ceil(x)

取大于或者等于x的最小整数.

4. math模块的floor(x)

取小于或者等于x的最大整数.

f = 11.2

math.floor(f)   向下取整   #11.0

math.ceil(f)     向上取整  #12.0

>>> x = 0.0
>>> for i in range(10):
	x += 0.1
	print(x)

	
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999

即:为什么有几行的输出看起来不对?

因为 Python 中使用双精度浮点数来存储小数。在 Python 使用的 IEEE 754 标准(52M/11E/1S)中,8字节64位存储空间分配了52位来存储浮点数的有效数字,11位存储指数,1位存储正负号,即这是一种二进制版的科学计数法格式。虽然52位有效数字看起来很多,但麻烦之处在于,二进制小数在表示有理数时极易遇到无限循环的问题。其中很多在十进制小数中是有限的,比如十进制的 1/10,在十进制中可以简单写为 0.1 ,但在二进制中,他得写成:0.0001100110011001100110011001100110011001100110011001…..(后面全是 1001 循环)。因为浮点数只有52位有效数字,从第53位开始,就舍入了。这样就造成了标题里提到的”浮点数精度损失“问题。 舍入(round)的规则为“0 舍 1 入”,所以有时候会稍大一点有时候会稍小一点。

Python 的浮点数类型有一个 .hex()方法,调用能够返回该浮点数的二进制浮点数格式的十六进制版本。这话听着有点绕,其实是这样的:本来浮点数应该有一个 .bin() 方法,用来返回其二进制浮点数格式。如果该方法存在的话,它看起来就像这样(p-4表示×2-4,或者可以简单理解为小数点 左移 4 位):