Ruby Enumerable 无法在最小函数中比较 BigDecimal NaN



如果我比较abc这样

[a,b,c].min

哪里

a = BigDecimal.new("NaN")
b = BigDecimal.new("NaN")
c = BigDecimal.new("0.0")

我得到:

ArgumentError: comparison of BigDecimal with BigDecimal failed

但是,如果我使用 ruby 的枚举最小值使用的比较运算符,那么我会得到这个:

irb(main):001:0>  a <=> b
=> nil
irb(main):002:0>  a <=> c
=> nil

并且不会呈现任何错误。这是 Ruby 内部的问题还是我误解了min,我可以使用其他东西来实现与 enumerable 的min相同的效果,并且不会爆炸?

来自 Ruby 语言文档:

NaN 从不被视为与任何其他值相同,即使 NaN 本身:

n = ::new('NaN')

n == 0.0 -> 无

n

== n -> nil

据我了解,NaN值的任何实例都是唯一且无与伦比的。

请考虑以下代码片段:

require 'bigdecimal'
a = BigDecimal('NaN')
b = BigDecimal('NaN')
puts a == b
puts a > b
puts a < b
对于

这些比较中的每一个,您都会得到falseminmax依赖于排序来产生结果,正如@phoffer指出的那样,sort根据第二个数字是否等于、大于或小于第一个数字生成 0、1 和 -1 的值。

TL;DR:任何时候你在操作中使用 NaN,你都不能期待有意义的结果。

如果您正在使用的 API 返回 NaN,您至少可以通过检测它来保护自己免受这种极端情况的影响。NaN 实际上是 Float 的一个实例,因此您可以使用 nan? 方法对其进行测试。

2.2.0 :002 > require 'bigdecimal'
 => true 
2.2.0 :003 > a = BigDecimal('NaN')
 => #<BigDecimal:7fae1b3bd050,'NaN',9(9)> 
2.2.0 :004 > a.nan?
 => true 

最新更新