2010-07-28 6 views
2

두 수식이 같은지 테스트하는 클래스의 인스턴스를 초기화하고 있습니다. Ruby에서의 연산 순서 질문

공식의 계산 된 값

실제로 동일 :

RubyChem::Chemical.new("SOOS").fw 
=> 96.0 

RubyChem::Chemical.new("OSSO").fw 
= 96.0 

나는이 두 인스턴스의 평등을 확인하는 새로운 클래스를 생성 할 때 내가있어 결과에 놀라게 비트 :

x = RubyChem::BalanceChem.new("SOOS","OSSO") 
x.balanced 
=>false 

y = RubyChem::BalanceChem.new("SOOS","SOOS") 
y.balanced 
=> true 

RubyChem :: BalanceChem는 방법이 여기에 초기화 :

def initialize(formula1, formula2) 
    @balanced = RubyChem::Chemical.new(formula1).fw == RubyChem::Chemical.new(formula2).fw 
end 

가 왜 FW를 가져 루비하지 않습니다 수식 1과 수식 2의 값을 비교하고 그 값의 동일성을 확인 하시겠습니까? Ruby의 작동 순서는 무엇이며 Ruby는 무엇을하고 있습니까? 이 문제에 대한 이해가 부족하다는 것을 알 수 있습니다. 이 작품을 어떻게 만들 수 있습니까? 미리 감사드립니다.

답변

3

당신은 아마 평등을위한 부동 소수점 숫자를 확인하고 싶지 않아요. 대신 델타를 비교해야합니다.

x = 1.000001 
y = 1.0 
x == y 
(x-y).abs < 0.00001 

그래서, 당신은 부동 소수점 연산에서 어떤 변화를 처리하는 것이 기분이 0.00001 같은 델타을 발견하고 그것을 그런 식으로 사용

은 IRB이보십시오. 결코 == 수레가 뜨지 않아야합니다.

+0

비교하기 위해 부동 소수점 대신 무엇을 사용 하시겠습니까? 화학에서 내가 필요로 할 수있는 가장 구체적인 것은 .00001; 수학 연산에서 부동 소수점을 사용하면 어떤 이점이 있습니까? –

+1

다른 유형 대신 부동 소수점을 사용하는 것이 뚜렷한 이점이 없으며, 중요한 숫자를 고려하고 반올림 문제를 처리해야하는 경우도 완벽하게 정확해야합니다. 그러나 모든 것을 10k 씩 곱하고 정수 수학을 사용하는 것은 문제가되기 때문에 지금은 수레를 고수 할 것입니다. 필요한 가장 정밀도가 .00001 인 경우 비교를 처리하는 가장 좋은 방법은 위에서 설명한 방법을 사용하여 (x-y) .abs <0.000001 정도를 사용하여 동등 함의 최대 차이로 사용하는 것입니다. 오류는 일반적으로 1e-9 범위를 넘어서므로 괜찮습니다. – drharris

4

루비 1.8은 bug when converting floats to string입니다. 때때로 주어진 문자열이 float을 잘 나타내지 못하는 경우가 있습니다. 두 분명히 동일한 결과가 실제로 동일하지 않은 이유

0.5600000000000005.to_s == 0.56.to_s #=> true 
# should have returned false, since: 
0.5600000000000005  == 0.56  #=> false 

이 설명 : 여기에 0.56와 예입니다.

오차 범위 내에서 비교를 수행하거나 비교하기 전에 반올림하거나 BigDecimal 또는 Rational과 같은 정확한 유형을 사용하는 것이 좋습니다.