3

なぜfalse2回目の比較で?ライブラリをロードしていません。

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

true私は1.8.7ですべてを取得します。どうしたの?

スクリプトを更新して、私が知る限り、フロートが同じであることを示しました。私は何かが足りないのですか?

4

2 に答える 2

4

Time.to_fのドキュメントから:「IEEE754 doubleは、エポックからのナノ秒数を表すのに十分な精度ではないことに注意してください。」@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ドキュメント:「IEEE754doubleは有理数を表すのに十分正確ではないため、#to_fとsubsecの最下位桁は異なります。正確な値はsubsecによって返されます。」

于 2012-09-14T22:32:45.007 に答える
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)は、両方の入力で同じ浮動小数点精度の損失があるため、入力は実際に同一であるためです。

したがって、要約すると、これはバグのある動作ですが、浮動小数点演算の基本的な警告に関連しているため、/それ自体はバグではありません。

于 2012-09-14T22:33:11.173 に答える