From: Mark Hubbart Date: 2005-04-15T07:33:12+09:00 Subject: Re: when 1.6 != 1.6? -- newbie On 4/14/05, Mel Bohince 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: > => # @beverage=#>> > > 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" 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