这看起来像红宝石时间平等错误吗?

时间:2012-09-14 22:07:53

标签: ruby time equality

为什么第二次比较中的false?我没有加载任何库。

puts RUBY_DESCRIPTION
t = Time.now
t1 = Time.at(t.to_f)
t2 = Time.at(t.to_f)
puts( t1 == t2 )
puts( t == t1 )
puts( t.to_f == t1.to_f )
printf "%.64f\n%.64f\n%.64f\n", t, t1, t2

输出:

ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]
true
false
true
1347661545.4348440170288085937500000000000000000000000000000000000000000000
1347661545.4348440170288085937500000000000000000000000000000000000000000000
1347661545.4348440170288085937500000000000000000000000000000000000000000000

我在1.8.7上获得所有true。发生了什么事?

据我所知,我更新了脚本以显示浮动是相同的。我错过了什么吗?

2 个答案:

答案 0 :(得分:4)

来自Time.to_f上的文档:“请注意,IEEE 754 double不足以表示Epoch的纳秒数。”为了说明@ oldrinb的评论:

puts RUBY_DESCRIPTION # ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]
t = Time.now
p t.subsec #=> (40189433/100000000); # a Rational, note the last digits 33
p t.to_f   #=> 1347661635.4018943   # last digit missing 3

Time#subsec documentation:“#to_f和subsec的最低位不同,因为IEEE 754 double不足以表示理性。准确的值由subsec返回。”

答案 1 :(得分:1)

我愿意打赌这是一个经典的浮点精度问题。具体来说,当您调用#to_f时,您可能会丢失原始对象中的精确度。

如果您比较每个对象的#nsec值,则可以轻松地看到这一点:

1.9.3p194 :059 > t = Time.now
 => 2012-09-14 15:29:59 -0700
1.9.3p194 :060 > t2 = Time.at(t.to_f)
 => 2012-09-14 15:29:59 -0700
1.9.3p194 :062 > t.nsec
 => 489932427
1.9.3p194 :063 > t2.nsec
 => 489932537

Time.at(t.to_f) == Time.at(t.to_f)可能成功的原因是两者在输入中都有相同的浮点精度损失,因此它们的输入确实相同。

所以,总而言之,这是一个错误的行为,但它不是一个错误/本身/,因为它与浮点运算的基本警告有关。