gpt4 book ai didi

ruby - 根据 ==,两个相等的 Time 对象不相等

转载 作者:数据小太阳 更新时间:2023-10-29 07:16:49 26 4
gpt4 key购买 nike

我在 Ruby 中发现了一些 Time 的行为,我在编写一些测试时不理解这些行为。我是否遗漏了什么或者这是一个真正的问题?

我可以按如下方式在 irb 中重现这种情况 - 首先创建一个 Time 并向其添加 30 秒:

t = Time.new(2007,01,15,11,15,30.1)
# => 2007-01-15 11:15:30 +0000
t1 = t + 30
# => 2007-01-15 11:16:00 +0000

然后创建另一个应该等于t1的时间:

t2 = Time.new(2007,01,15,11,16,0.1)
# => 2007-01-15 11:16:00 +0000

现在我希望 t1t2 相等,但根据 == 它们不相等。从我所做的粗略实验来看,== 似乎有效,除非添加秒数将 t1 移到新的一分钟:

t1 == t2
# => false

但是,如果您对它们调用 to_f,则 == 会返回 true:

t1.to_f == t2.to_f
# => true

只是为了确认没有任何纳秒:

t1.nsec
# => 100000000
t2.nsec
# => 100000000

=== 在 joanbm 和 Vitalii Elenhaupt 的回答后添加(很抱歉再次打开它)

joanbm 和 Vitalii Elenhaupt 指出 t1.to_rt2.to_r 产生不同的结果。

但是……根据Ruby-Doc正常范围内的 Time 存储为自纪元以来纳秒数的 63 位整数 - 这表明不应涉及 float 问题。

那么...为什么如果 Time 存储为整数,而 #to_f#nsec 可以产生相同的结果到小数点后 9 位,不能 == 使用此信息来识别两次相等? (也许 Ruby 在相等性测试中使用 #to_r?)。

并且...可以安全地假设 t1.to_f == t2.to_f 将始终准确测试小数点后 9 位是否相等,并且这是比较 的最佳方式>时间对象?

最佳答案

这是 notorious计算机中 float 表示不准确的问题,与 Ruby 或 Time 类实现无关。

您将 float 作为秒参数赋予两个对象,并且其(不准确的)小数部分构造函数存储为其内部表示的有理数:

t = Time.new(2007,01,15,11,15,30.1)
t.subsec # (14073748835533/140737488355328) <- may vary on your system
t.subsec.to_f # 0.10000000000000142 <- this is not equal to 0.1 !!

第二次dtto:

t2 = Time.new(2007,01,15,11,16,0.1)
t2.subsec # (3602879701896397/36028797018963968)
t2.subsec.to_f # 0.1 <- there accidentally precision didn't get lost

只需使用像 Rational 这样的精确数值类型就可以了:

t = Time.new(2007,01,15,11,15,Rational('30.1'))
t1 = t + 30

t2=Time.new(2007,01,15,11,16,0.1r) # alternate notation, see docs

t1 == t2 # true

或者用两边应用的Time#round方法粗略对比

关于ruby - 根据 ==,两个相等的 Time 对象不相等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31687361/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com