2023-05-29 20:06:27
0.1 + 0.2 != 0.3 的问题根源在于计算机使用二进制浮点数表示时无法精确存储十进制小数 0.1 和 0.2,导致累加结果存在微小误差。
一、二进制浮点数的存储原理计算机采用 IEEE 754 标准存储浮点数,其核心是将数值分解为:
例如,十进制数 0.1 的二进制科学表示法为:0.1 = 1.10011001100110011001100... × 2??(二进制小数 0.0001100110011... 是无限循环的)
由于尾数位数有限(如单精度 23 位,双精度 52 位),无限循环的二进制小数会被截断,导致存储的值是一个近似值。
二、0.1 和 0.2 的二进制近似存储0.1 的二进制近似值实际存储为:0.1000000000000000055511151231257827021181583404541015625(双精度)
0.2 的二进制近似值实际存储为:0.200000000000000011102230246251565404236316680908203125(双精度)
累加后的误差0.1 + 0.2 的理论结果应为 0.3,但实际计算为:0.3000000000000000444089209850062616169452667236328125与 0.3 的二进制存储值 0.299999999999999988897769753748434595763683319091796875 不完全一致。
十进制有限小数 ≠ 二进制有限小数类似 0.1(1/10)在十进制中是有限小数,但在二进制中是无限循环小数(类似十进制的 1/3=0.333...)。
IEEE 754 的截断误差存储时只能保留有限位数,导致微小误差累积。例如:
0.1 + 0.2 # 输出 0.30000000000000004使用容差(Tolerance)比较替代 ==,改用误差范围判断:
def is_equal(a, b, tolerance=1e-9): return abs(a - b) < tolerance转换为整数运算例如处理货币时,用“分”代替“元”避免小数:
0.1元 + 0.2元 → 10分 + 20分 = 30分 → 0.3元使用高精度库
Python 的 decimal 模块:
from decimal import DecimalDecimal('0.1') + Decimal('0.2') == Decimal('0.3') # TrueJava 的 BigDecimal。
格式化输出显示时限制小数位数:
print("{0:.1f}".format(0.1 + 0.2)) # 输出 0.3通过理解二进制浮点数的底层原理,可以更理性地处理这类“反直觉”现象。