You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Minitest assert_equal断言失败咨询:数值看似相等却不匹配

浮点数精度坑导致的Minitest断言失败?看这里解决

嘿,这个问题我之前也碰到过!本质上是浮点数的二进制存储特性和Minitest assert_equal 的严格比较逻辑在搞鬼,咱们一步步说清楚:

为啥明明数值一样却断言失败?

你看到的 -0.904e1 其实就是 -9.04 的科学计数法写法,数值上完全等价,但Minitest的 assert_equal 对浮点数是严格的数值相等校验——而计算机里的浮点数是用二进制存储的,很多十进制小数根本没法被精确表示。哪怕你调用了 round(2),最终得到的浮点数在内存里的二进制表示,可能和你直接写的 -9.04 字面量存在极其细微的差异。

举个实际的例子:假设 elts[2].change 的原始值是 -9.040000000000001,round(2) 之后打印出来是 -9.04,但它的底层存储和你写的 -9.04 字面量并不完全一样;反过来如果原始值是 -9.039999999999999,round(2) 后显示也是 -9.04,但同样和字面量的存储有差别。这种细微差异就会让 assert_equal 判定两者不相等。

至于科学计数法的显示,只是Ruby输出浮点数的一种格式而已,本质还是同一个数值范围,核心问题还是精度。

怎么解决?

别用 assert_equal 来比较浮点数!Minitest专门提供了 assert_in_delta 方法,它允许你设置一个可接受的误差范围,完美避开浮点数精度的坑:

# 允许±0.001的误差,完全覆盖两位小数的精度需求
assert_in_delta -9.04, elts[2].change.round(2), 0.001

如果你的业务场景要求绝对精确的十进制运算(比如财务相关),那更推荐用Ruby的 BigDecimal 类型来处理,从根源上避免浮点数精度问题:

require 'bigdecimal'

expected = BigDecimal("-9.04")
actual = BigDecimal(elts[2].change.to_s).round(2)
assert_equal expected, actual

为啥其他测试能过?

运气好而已😂 其他测试的数值刚好能被二进制精确表示,或者它们的精度差异小到没触发这个问题。而这个测试的数值刚好踩中了浮点数的精度盲区,导致存储表示和字面量不一致,才暴露了问题。

内容的提问来源于stack exchange,提问作者Andrew Cetinic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:28:13