On 4/14/05, Mel Bohince <feet / att.net> wrote:
> Really enjoying Ruby so far, but now I'm confused. To help learn Ruby,
> I've been translating the Java code in the "Head First Design Patterns"
> book into Ruby, aware that many are built-in with Ruby. While mimicking
> the Decorator pattern I'm getting a strange failure to an assert_equal.
> 
> The unit test excerpts:
> @e = Expresso.new
> @e.setSize('grande')
> @e = Mocha.new(@e)
>                 assert_equal(1.40, @e.cost(),"price check") --> pass
> @e = Mocha.new(@e)
>                 assert_equal("Expresso, Mocha, Mocha", @e.getDescription()) --> pass
> #puts @e.cost() --> 1.6 ##sanity check, should be 1.00 + 0.20 + 0.20 +
> 0.20 = 1.6
> #####
> assert_equal(1.6, @e.cost(),"price check2") --> fail with:
> 
>    1) Failure:
> testConcreteCondiment(TestBeverages)
> [/Users/mel/Documents/Ruby_files/patterns/decorator/test/
> testbeverages.rb:70]:
> price check2.
> <1.6> expected but was
> <1.6>.
> 5 tests, 21 assertions, 1 failures, 0 errors
> 
> Recreated in irb, the instance looks like:
> => #<Mocha:0x7a884 @beverage=#<Mocha:0x21c94
> @beverage=#<Expresso:0x58310 @description="Expresso", @size=0.2>>>
> 
> Any clues to what I'm doing wrong? Is there a strategy to debug this
> kind of thing? The debugger is not like I'm use too.
> 
> Thanks for any help you can offer.

Here's a nice page that with a self-explanitory title:

"What Every Computer Scientist Should Know About Floating-Point Arithmetic"
  <http://docs.sun.com/source/806-3568/ncg_goldberg.html>

The way money is usually handled is to either use integers for
pennies, or use a separate money class which stores money in that way.
A nice thing about doing this in Ruby is that once you create your
money class, you can add helper methods to Numeric:

class Numeric
  def cents
    Money.new(self.round)
  end
  def dollars
    Money.new((self*100).round)
  end
end

23.cents #==> $0.23
23.50.dollars #==> $23.50

cheers,
Mark