【问题标题】:Ruby Float#round behaviour change after updateRuby Float#round 更新后的行为变化
【发布时间】:2019-01-14 14:43:03
【问题描述】:

我正在将存储库从 Ruby 版本 2.3.3 升级到 2.5.1。测试失败,我已将原因缩小到以下行为:

In version 2.3.3 1.34875.round(4) => 1.3487

In version 2.5.1 1.34875.round(4) => 1.3488

现在,我知道this change,但我认为这无关紧要,因为 a) 默认行为被单独保留,b) 观察到的更改与建议的默认更改相反。我也知道浮点数不是准确存储有限小数的好方法,并且精度的一些变化可能解释了为什么会发生这种变化。但是我不知道,也不知道怎么查。

【问题讨论】:

  • 您的第一个示例看起来被截断而不是四舍五入...
  • @Anthony 不过,这就是你在 2.3.3 中得到的结果

标签: ruby floating-point upgrade compatibility


【解决方案1】:

默认行为并不像您建议的那样“单独存在”。有一个新的策略来四舍五入到最接近的偶数:https://github.com/ruby/ruby/blob/8d7c380216809ba5bd4a3eec41d7dda61f825ffa/NEWS#core-classes-updates-outstanding-ones-only(搜索round)。

你可以使用

> 1.34875.round(4, half: :down)
=> 1.3487 

为了保留似乎是 2.3.3 中的行为。

【讨论】:

  • github.com/ruby/ruby/blob/v2_4_0/… 在这里更相关;在该提交之后和发布之前更改了默认值(如问题中链接的错误中所述)。发布的行为是,并且一直是,half: :up
  • 我认为这不是真的。如果你调用 0.5.round,1.5.round, 2.5.round 等等(在 2.3.3 和 2.5.1 中)你会得到 1,2,3,... 而不是 0,2,2,...就像默认行为发生变化一样。确实,我很确定您引用的更改是在 OP 的链接中还原的更改。
  • @matthewd 你是 100% 肯定的吗?我记得读过一篇关于为什么舍入到甚至给出更均匀的舍入或某事的文章。并且很确定这在某个时候是 ruby​​ 中的一种行为......
【解决方案2】:

您描述的行为听起来像https://bugs.ruby-lang.org/issues/13138,这被认为是一个错误修复并向后移植到 2.3.5。 (我还没有确认它被反向移植到哪个 2.4.x,如果有的话,但它在 2.5.0 之前的主干中。)

正如您所推测的,这是一个精度问题。 1.34875 的浮点表示略小于 1.34875,因此 2.3.3 做了技术上过于正确的事情并向下取整;较新的版本认识到,考虑到浮点数实际上代表一系列值 [包括 1.34875],四舍五入更加一致。

【讨论】:

  • 这对我来说似乎是合理的——我也认为它是一个错误修复。我想重新定义 round 以复制旧行为,以便我可以查看我的测试失败是由于此特定更改还是由于我需要调查的另一个更改。你能想出一个办法吗? (我真的不知道如何阅读您提供的链接)
  • 不,它似乎太低了,无法有效地覆盖(没有在 ruby​​-land 中完全重新实现舍入,这似乎......不好玩)。我建议在 2.3.3 上更改您的测试,以便最终使用不同的值(在两个版本中都“正常”四舍五入);如果修改后的测试在升级后仍然通过,那对我来说已经足够了。
  • 可以编译一个自定义的 ruby​​ 构建并使用 github.com/ruby/ruby/commit/… reverted...但是这似乎更有可能引入不确定性而不是消除它,IMO。
  • 很公平,它们中的许多是自动生成的,并且很难测试,以至于我们进行了很多长的直接字符串比较(我知道这是一件坏事)。我定义了一个 round 方法,它调用 super 并输出“#{foo} rounds to #{bar}”,这样如果我看到更改并同意舍入,我可以忽略失败并检查其他失败。不完美,但易于管理。感谢您的回答!
  • 按照这些思路,我想您可以定义一个常量哈希表来覆盖某些浮点数及其舍入:您不必在算法上重现旧行为,只需针对您的特定数字强制它'再次相遇。
猜你喜欢
  • 2012-09-09
  • 2013-03-22
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 2013-11-15
  • 1970-01-01
相关资源
最近更新 更多