5.0/4 == 1.25 => trueand works appropriately for other types as well.
5.0/4 == 1.24 => false
This is just fine for numbers, until you have to fight round-off:
5.0/3 == 1.6666667 => falseBecause we're dealing with arbitrary numeric precision in Ruby, there really isn't a "close-enough" option. Instead we have to define it ourselves.
Before we jump into that however, let's consider Ruby's pattern matching facilities. Ruby defines pattern matching using an equal-tilde (=~) to match regular expressions against strings - the return value is the offset into the string of the start of the match, or nil if the string did not contain the pattern. Regular expressions are baked right into Ruby as part of the language, giving you direct access to matching.
The =~ was not chosen for matching patterns indiscriminately. In mathematics, the tilde combined with equals typically means "congruent" or "approximately equal to". The expression on the left numerically "matches" the expression on the right, within some tolerance.
Well, since the =~ isn't being used for Numerics in Ruby, there's no reason we can't make it do double duty. We can define a little code that will do our approximate numerical matching for us.
@@epsilon = 0.0001
@@epsilon = epsilon.abs
(self - value).abs < epsilon
alias =~ approximately_equals
Defining the operations on Numeric mean that any number will have the ability to do close matching as well as precise equality.
5.0/3 =~ 1.6666 => true
The precision of the tests can be set by adjusting the epsilon value in Numeric, or specifying it directly when calling the approximately_equals method
Numeric.epsilon = 0.00001
5.0/3 =~ 1.6666 => false
(5.0/3).approximately_equals(1.66,0.01) => true
(5/3).approximately_equals(1,0.5) => true
Yes, it is truly wonderful that Ruby gives you the ability to roll your own meanings to operations. Letting you deal with issues such as these really gets you past some gritty code issues with elegance.