
刚到了一个温湿度传感器,我就把他接入到八哥开关小帮手上面。 数据是通过Modbus-RTU的协议传输到服务器上,是一个整型 int16AB 编码,刚好是10倍的关系, 计算公式为 value = 0.1 * read_value。 计算出来的数据很奇怪,18.9000000000002,后面多出来了好多的小数点,用眼睛看就知道有问题了。 我们希望的是得到 18.9,但计算机给出了一个带有微小“尾巴”的数字。这并不是 Python 的 bug,而是计算机底层存储浮点数方式导致的物理限制。
在十进制中,

是无限循环小数 (0.3333...);同理,在二进制中,

(即 0.1) 也是一个无限循环小数:

因为计算机的存储空间(53位有效数字)是有限的,它必须在某一位进行截断。这种截断导致了微小的精度丢失,就像把 0.3333... 截断为 0.3333 一样,结果虽然极其接近,但在数学上并不完全相等。
Decimal 模块模拟了人类手算的方式,避免了二进制转换误差,这样我们算出来的数据就不会出现那么多的小数位了。
Python
from decimal import Decimal# 核心原则:必须以 '字符串' 形式初始化a = Decimal('189')b = Decimal('0.1')print(a * b) # 输出: 18.9 (类型为 Decimal)警告:如果写成
Decimal(0.1),由于括号内的 0.1 已经是浮点数,误差会被带入Decimal中,导致前功尽弃。
经过 Decimal 的处理,终于可以计算出正确的数字了,没有那么多的小数位。