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.
Ruby 1.8.2 on OSX 10.3.8
-: -: -: -: -: -: -: -: \|/
-: -: -: -: -: -: -: -: cU
Mel Bohince
Project Manager,
Arkay Packaging Corporation
fe...@att.net
> Any clues to what I'm doing wrong?
When you're using assert_equal, you're comparing two floating point
numbers with ==. That's usually a bad idea, because rounding errors
can/will occur. Try using assert_in_delta(number1, number2, delta), to
find out, if |number1 - number2| <= delta instead.
Another tip: If you want to represent prices in your programs, don't use
floats at all. Use integers for the representation of the cent values
and all computations, and divide by 100 only for the string
representation of the numbers.
--
Florian Frank
> <1.6> expected but was
> <1.6>.
Floating point accuracy, the bane of mankind.
1.0 + 0.2 + 0.2 + 0.2 - 1.6
=> -2.22044604925031e-16
> 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.
Either do fixed-point decimals with integers and decimal point
divisor (100 => 1.00*100; 100 + 20 + 20 + 20 - 160 => 0)
or pick an error threshold and check that (a - b) < threshold
(1.0 + 0.2 + 0.2 + 0.2 - 1.6) < 0.01
=> true
I've found that a lot of those classical design patterns don't really
make much sense when using a duck-typed language.
Thoughts?
Just use BigDecimal. No need to get tricky.
--
Neil Stevens - ne...@hakubi.us
'A republic, if you can keep it.' -- Benjamin Franklin
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
Ilmari is right here. The way to check if the calculated value is close
enough to the expected value, please check:
http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html#M000104
Usage being something like
required_accuracy = 0.0001
assert_equal(1.6, @e.cost(), required_accuracy,
"price check2") # --> does not fail anymore
- Aleksi
Douglas
Thanks to all for the help!
I'll remember the assert_in_delta in the future when testing on floats.
The point about avoiding float when doing currency is sound advice, yet
opens a new chapter of issues when deal with big numbers in special
pricing units of measure. Then Googled "Class Money" got a spiffy
"ruby" Money at <http://www2a.biglobe.ne.jp/~seki/ruby/sbpp8.html> and
a nice interface from junit.samples.money; ah, other have blazed and
paved the trail.
Thanks.
-: -: -: -: -: -: -: -: \|/
-: -: -: -: -: -: -: -: cU
mel
I'll defer to experienced, but yes, it seems like overkill when not a
strongly-typed lng.
I just wanted some hands-on experience as I read the Pick-Ax; thought
that working with some classic coding situations would be a good
contrived problem that would help me retain Ruby. (I spend most of my
work day writing in 4D which is not OO.) Also, the "Head First" book is
really motivating; the writing style is truly impressive.
-: -: -: -: -: -: -: -: \|/
-: -: -: -: -: -: -: -: cU
mel