W
William James
2 Always use
(x-y).abs < (x.abs + y.abs) * Float::EPSILON)
as a test for equality.
Better than the first proposal, but won't work if the rounding error
gets too large after a complex computation.
In addition, (1) and (2) suffer from the problem that x==y and y==z do
not imply x==z.
How about
(a - b).abs / [a, b].map{|x| a.abs}.min < Float::EPSILON
?
def eq( a, b )
(a - b).abs / [a, b].map{|x| a.abs}.min < Float::EPSILON
end
DATA.each{|s|
strings = s.chomp.split(";")
floats = strings.map{|s| eval(s) }
puts strings.join( " == " ) +
" : #{floats[0]==floats[1]} #{ eq( *floats ) }"
}
__END__
(0.05+0.01);0.06
(0.34+0.01);0.35
9.123456789;9.1234567891
9.123456789012345;9.1234567890123451
9.12345678901234e-9;9.123456789012341e-9
=== output ===
(0.05+0.01) == 0.06 : false true
(0.34+0.01) == 0.35 : false true
9.123456789 == 9.1234567891 : false false
9.123456789012345 == 9.1234567890123451 : false true
9.12345678901234e-9 == 9.123456789012341e-9 : false true