一、背景
-
计算机基本上使用二进制数字,即 0 或 1表示;
十进制: 1 / 3 = 0.3333333333… 无限循环的情况
浮点数的总数是无限且不可数的,浮点数在计算机占用的内存是有限的,如果表示计算机内存则占满
不可能用有限的内存空间存储无限多的浮点,后面多余的部分都会被砍掉 -
计算机的浮点类型也是由二进制表示的 浮点标准
同上并不是所有的十进制数都可以用二进制格式精确表示,
有些是使用有限数量的二进制数字来近似的
例如 浮点型0.1 转化二进制的结果 0.00011001100110011001100110011001100110011001100…
二、浮点数转二进制计算方法
-
1. 对十进制小数乘2得到的整数部分和小数部分 2. 整数部分即是相应的二进制数码 3. 再用2乘小数部分,又得到整数和小数部分 4. 不断重复,直到小数部分为0或达到精度要求为止 5. 第一次所得到为最高位,最后一次得到为最低位
-
0.25 * 2 = 0.5 整数部分 0 小数部分 5 0.5 * 2 = 1.0 整数部分 1 小数部分 0 浮点型0.25 转化二进制的结果 0.01
-
0.8125 * 2 = 1.625 整数部分 1 小数部分 625 0.625 * 2 = 1.25 整数部分 1 小数部分 25 0.25 * 2 = 0.5 整数部分 0 小数部分 5 0.5 * 2 = 1.0 整数部分 1 小数部分 0 浮点型0.8125 转化二进制的结果 0.1101
-
0.1 * 2 = 0.2 整数部分 0 小数部分 2 0.2 * 2 = 0.4 整数部分 0 小数部分 4 0.4 * 2 = 0.8 整数部分 0 小数部分 8 0.8 * 2 = 1.6 整数部分 1 小数部分 6 0.6 * 2 = 1.2 整数部分 1 小数部分 2 0.2 * 2 = 0.4 整数部分 0 小数部分 4 0.4 * 2 = 0.8 整数部分 0 小数部分 8 0.8 * 2 = 1.6 整数部分 1 小数部分 6 0.6 * 2 = 1.2 整数部分 1 小数部分 2 ... .... ....... 浮点型0.1 转化二进制的结果 0.0001100110011001100110011001100110...
结论
浮点数是以二进制形式存储的,将浮点数转化为二进制过程中,也会出现无限循环的情况,造成结果的不准确
三、 浮点数精度丢失解决 例如:0.1 + 0.2 问题
浮点数精度丢失通常在涉及不能精确表示为有限小数的数字时发生,
例如 0.1 或 0.2 这样的数字,因为它们在二进制表示中是无限循环小数。
由于计算机的二进制表示是有限的,所以在转换为二进制表示时会有一定的近似,从而导致小数的精度问题。
一、背景
-
计算机基本上使用二进制数字,即 0 或 1表示;
十进制: 1 / 3 = 0.3333333333… 无限循环的情况
浮点数的总数是无限且不可数的,浮点数在计算机占用的内存是有限的,如果表示计算机内存则占满
不可能用有限的内存空间存储无限多的浮点,后面多余的部分都会被砍掉 -
计算机的浮点类型也是由二进制表示的 浮点标准
同上并不是所有的十进制数都可以用二进制格式精确表示,
有些是使用有限数量的二进制数字来近似的
例如 浮点型0.1 转化二进制的结果 0.00011001100110011001100110011001100110011001100…
二、浮点数转二进制计算方法
-
1. 对十进制小数乘2得到的整数部分和小数部分 2. 整数部分即是相应的二进制数码 3. 再用2乘小数部分,又得到整数和小数部分 4. 不断重复,直到小数部分为0或达到精度要求为止 5. 第一次所得到为最高位,最后一次得到为最低位
-
0.25 * 2 = 0.5 整数部分 0 小数部分 5 0.5 * 2 = 1.0 整数部分 1 小数部分 0 浮点型0.25 转化二进制的结果 0.01
-
0.8125 * 2 = 1.625 整数部分 1 小数部分 625 0.625 * 2 = 1.25 整数部分 1 小数部分 25 0.25 * 2 = 0.5 整数部分 0 小数部分 5 0.5 * 2 = 1.0 整数部分 1 小数部分 0 浮点型0.8125 转化二进制的结果 0.1101
-
0.1 * 2 = 0.2 整数部分 0 小数部分 2 0.2 * 2 = 0.4 整数部分 0 小数部分 4 0.4 * 2 = 0.8 整数部分 0 小数部分 8 0.8 * 2 = 1.6 整数部分 1 小数部分 6 0.6 * 2 = 1.2 整数部分 1 小数部分 2 0.2 * 2 = 0.4 整数部分 0 小数部分 4 0.4 * 2 = 0.8 整数部分 0 小数部分 8 0.8 * 2 = 1.6 整数部分 1 小数部分 6 0.6 * 2 = 1.2 整数部分 1 小数部分 2 ... .... ....... 浮点型0.1 转化二进制的结果 0.0001100110011001100110011001100110...
结论
浮点数是以二进制形式存储的,将浮点数转化为二进制过程中,也会出现无限循环的情况,造成结果的不准确
三、 浮点数精度丢失解决 例如:0.1 + 0.2 问题
浮点数精度丢失通常在涉及不能精确表示为有限小数的数字时发生,
例如 0.1 或 0.2 这样的数字,因为它们在二进制表示中是无限循环小数。
由于计算机的二进制表示是有限的,所以在转换为二进制表示时会有一定的近似,从而导致小数的精度问题。
0.1 0.00011001100110011001100110011001100110011001101...
0.2 0011001100110011001100110011001100110011001100110...
python是以双精度(64bit)来保存浮点数的,后面多余的会被砍掉,所以在电脑上实际保存的已经小于0.1的值了,后面拿来參与运算就产生了误差
- 对稳定性、安全性要求非常高的程序,尽量避开浮点数
- 使用 Decimal 类型:提供了更高的精度,能避免浮点数运算的一些常见问题
from decimal import Decimal a = Decimal('0.1') + Decimal('0.2') print(float(result)) # 将结果转换为浮点数输出,得到正确的结果:0.3
四、0.1 + 0.3 呢
0.1(10) ≈ 0.0001100110011001100110011001100110011001100110011001101...(2)
0.3(10) ≈ 0.0100110011001100110011001100110011001100110011001101...(2)
0.0001100110011001100110011001100110011001100110011001101...(2)
+
0.0100110011001100110011001100110011001100110011001101...(2)
=
0.0110011001100110011001100110011001100110011001101101...(2)
将上述二进制结果转换回十进制,它大约等于 0.4(10)。
注意,这个结果仍然是一个近似值,因为我们只取了有限位数的二进制表示进行计算。
0.1 + 0.3二进制 0.0110011001100110011001100110011001100110011001101101...
0.4 二进制 0.0110011001100110011001100110011001100110011001100110...
在十进制中,0.1 + 0.3 确实等于 0.4。
在计算机内部,由于浮点数的二进制表示和有限精度,0.1 + 0.3 的二进制近似值并不等于 0.4 的二进制近似值。
因此,在某些情况下,由于浮点数精度问题,可能会导致 0.1 + 0.3 不等于 0.4。