在python中定义两个浮点型变量,值分别为1.1和2.2,两者相加并输出结果,结果并非为我们直观得到的3.3,而是趋近于3.3的一个小数值。 代码如下:
n1 = 1.1 n2 = 2.2 print(n1+n2)输出结果:
3.3000000000000003为什么会出现这种情况呢?
计算机中只有0和1,所有数据在计算机中都是以0和1的形式存储的,在机器字长有限的情况下,浮点数(小数)的精度也是有限的。 举个例子: 假如用一个8位的变量表示-1—1之间的小数,8位的变量共有0~255共256种不同的状态,那么最小的分度就是2/256=0.0078125,如果遇到比0.0078125更小的刻度就会造成精度损失导致数据不够精确。
那么计算机中的浮点数究竟是如何存储的呢?
IEEE 754标准规定浮点数的存储包括三部分,分别为“数符”(表示数值正负)、“阶码”和“尾数”。(类似于科学计数法) IEEE 754标准规定常用的浮点数格式有短浮点数(单精度、float型)、长浮点数(双精度、double型)和临时浮点数。
各类浮点数的位长如下: IEEE 754标准的浮点数中(临时浮点数除外),尾数采取隐藏位策略的原码表示,阶码用移码表示。 Ps: ① 隐藏位策略是指对于规格化的二进制浮点数,数值的最高位总是“1”,为了充分利用存储字长,将这个“1”隐含。 例如:(12)10=(1100)2,规格化后结果为1.1×23,其中整数部分的“1”默认不再存储。 ②移码是指一个n+1位的数值,在真值基础上加上一个2n的偏置值。 例如:一个八位数:x=(12)10=(0000 1100)2 [x]移=27+(0000 1100)2=1000 1100 但在浮点数的阶码中为了表示无穷大的数值,将移码为全1的状态空出来表示无穷大,故在阶码中的偏置值为2n-1,同时将移码为全0的状态空出来表示非规格化数。 即在长浮点数的存储中,阶码E的取值为1~2046。 即规格化长浮点数的真值为:(-1S)×1.M×2E-1023 S=0为正数,S=1为负数。
浮点数的表示范围如下: 知道了浮点数在计算机中的存储原理自然就能明白为什么浮点数的运算结果不够准确了。 以十进制数1.1为例,(1.1)10=(1.0001100110011)2 (0011无限循环) 规格化后结果为: (-10)×1. 0001100110011001100110011001100110011001100110011001×20 其中S=0,E=(1023)10, M=(0001100110011001100110011001100110011001100110011001)2 也就是说1.1以长浮点数的形式实际在内存空间中存储的是: (0011 1111 1111 0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001)2=(3FF1 9999 9999 9999)16
这个值并不是准确的1.1,而是一个近似的值,因而在运算时就会造成运算结果不够精确。 Python中的浮点数就是以64位长浮点数的形式存储在内存空间中的,在使用浮点数表示精确值的时候需要注意浮点数的精度。