JZ.
JZ.

Reputation: 21907

Order of operations question in Ruby

I'm initializing an instance of a class that tests the equality of two formulas.

The formula's calculated values are in fact equal:

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

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

When I created a new class to check the equality of these two instances I'm a bit surprised by the results:

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

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

the RubyChem::BalanceChem initialize method is here:

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

Why doesn't ruby fetch the fw values for formula1 and formula2 and check the equality of those values? What are the order of operations in Ruby and what is Ruby doing? I can see I lack an understanding of this issue. How can I make this work? Thank you in advance.

Upvotes: 2

Views: 942

Answers (3)

Marc-André Lafortune
Marc-André Lafortune

Reputation: 79622

Ruby 1.8 has a bug when converting floats to string. Sometimes the given string not a good representation of the float. Here is an example with 0.56:

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

This explains why two apparently identical results are not actually identical.

You probably want to do compare within a certain margin of error, do some rounding before doing a comparison, or use exact types like BigDecimal or Rational.

Upvotes: 4

drharris
drharris

Reputation: 11204

You probably do not want to check floating point numbers for equality. Instead, you should compare deltas.

Try this in irb:

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

So, you find a delta like 0.00001 that you feel would handle any variation in floating point arithmetic, and use it that way. You should never == floats.

Upvotes: 3

NullUserException
NullUserException

Reputation: 85488

This is likely another problem caused by floating point precision.

I can assure you that those values calculated before the equality is evaluated.

See the Ruby's operator precedence

Upvotes: 2

Related Questions