原文首发于 TechNova: 撮合引擎中的精度之殇:从浮点数陷阱到定点数救赎
承接页(解决方案):https://technologynova.org/solution/
DECIMAL,并统一“度量衡”。BigDecimal 很安全,但在撮合热点路径会引入对象分配、GC 与缓存不友好;高吞吐场景更常用int64 定点数(并配套溢出与舍入策略)。
在金融交易系统里,数值表示方式直接决定了:订单簿索引能不能命中、成交金额能不能对账、主备切换能不能严格一致。
经典示例是 0.1 + 0.2 输出 0.30000000000000004。这不是“打印格式问题”,而是 IEEE754 的二进制表示天然无法精确表达很多十进制小数。
0.3 与 0.1+0.2 的二进制表示不同,可能导致“看起来相等、实际上不等”。
IEEE754 用符号位 + 指数 + 尾数表示浮点数,能覆盖很大范围,但尾数本质是二进制小数。
十进制里常见的 0.1、0.2 在二进制下是无限循环小数,只能用“最接近的可表示值”近似。
这意味着:误差从“存进去那一刻”就已经存在。
核心思想:统一缩放因子(scale),把小数转成整数存储与计算。
例如价格保留 4 位:price_int = price * 10^4;数量保留 8 位:qty_int = qty * 10^8。
内部只做整数加减乘除(或在中间计算用更宽位宽),保证确定性与性能。
price_int * qty_int 可能超出 int64;用 __int128(C++)、BigInteger(Java)或受控拆分方案做中间计算。精度只是“交易核心能不能活下去”的第一关。真正上线还要把:订单生命周期(OMS)、风控、撮合分片、行情发布、清算对账、容灾演练串起来。 如果你在规划/重构交易系统,建议先从解决方案页对齐模块边界与落地路径: https://technologynova.org/solution/