2012-09-14 1 views
3

2 차 비교에서 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의를 얻을. 무슨 일이야?

나는 플로트가 동일하다는 것을 보여주기 위해 스크립트를 업데이트했다. 내가 놓친 게 있니?

+1

이것은 1.8.7에서 작동하는 것을 설명하지는 않지만'to_f'는 정밀도를 잃어 버린다는 것을 기억하십시오. – oldrinb

답변

4

문서에서 Time.to_f : "IEEE 754 double은 Epoch의 나노초 수를 나타낼만큼 정확하지 않습니다." ". IEEE 754 배는 정확한 값이 SUBSEC에 의해 반환되는 합리적인를 대표 할만큼 정확하지 않기 때문에 #to_f의 가장 낮은 자리를하고 SUBSEC는 다르다."

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 :의 oldrinb 코멘트 @ 설명하기 위해

+0

정보를 제공해 주셔서 감사합니다. 'subsec'에 대해서는 전혀 몰랐습니다. – Kelvin

+0

@Kelvin : 어느 쪽도 당신의 질문 앞에하지 않았다 :). 그러나이 방법은 1.8.7에는 존재하지 않았으므로 나노초를 Rational로 저장하는 것이 아마도 1.9 개선 일 것입니다. – steenslag

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) 가능성이 성공하는 이유는 자신의 입력이 실제로 그래서 모두가 자신의 입력에서 동일한 float 정밀도 손실을 가지고있다

같은.

요약하면 버그가있는 동작이지만 버그/당연하지 않습니다. 플로트 계산의 근본적인 경고에 묶여 있기 때문입니다.

+0

도움이된다는 측면에서 당신과 steenslag 사이에 일종의 동점입니다. 'nsec'에 대한 좋은 정보. 내가 본 새로운 1.9 기능입니다. – Kelvin