Greg Hauptmann
2009-Jan-11 08:17 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
Hi, Any suggestions on how to write an rspec expectation for equality when you get a BigDecimal back. I see that "big_decimal_variable.should == 123.23" doesn''t work as the ruby BigDecimal comparison (via ==) to the same Float value gives false (not true as you''d expect). For background / as an example see below: ?> bd => #<BigDecimal:221832c,''-0.32303E3'',8(12)> >> f => -323.03 >> f.class => Float >> bd.should == f Spec::Expectations::ExpectationNotMetError: expected: -323.03, got: #<BigDecimal:221832c,''-0.32303E3'',8(12)> (using ==) from /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/expectations.rb:52:in `fail_with'' from /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/matchers/operator_matcher.rb:46:in `fail_with_message'' from /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/matchers/operator_matcher.rb:61:in `__delegate_method_missing_to_given'' from /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/matchers/operator_matcher.rb:12:in `=='' from (irb):73 >> bd == f => false >> f == bd => false thanks Greg -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090111/d2c3aa60/attachment.html>
Mark Wilden
2009-Jan-11 09:23 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
On Sun, Jan 11, 2009 at 12:17 AM, Greg Hauptmann < greg.hauptmann.ruby at gmail.com> wrote:> > Any suggestions on how to write an rspec expectation for equality when you > get a BigDecimal back. I see that "big_decimal_variable.should == 123.23" > doesn''t work as the ruby BigDecimal comparison (via ==) to the same Float > value gives false (not true as you''d expect). >How about bd.to_s.should == 123.23.to_s ? ///ark -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090111/4312ca27/attachment.html>
Greg Hauptmann
2009-Jan-11 10:05 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
I''ve gone with the following ai.amount.should == BigDecimal(''-323.03'') However I''m still a bit surprised that Ruby itself does allow a good "==" test between a Float and a BigDecimal. Perhaps there''s a reason that I''m missing? On Sun, Jan 11, 2009 at 7:23 PM, Mark Wilden <mark at mwilden.com> wrote:> On Sun, Jan 11, 2009 at 12:17 AM, Greg Hauptmann < > greg.hauptmann.ruby at gmail.com> wrote: > >> >> Any suggestions on how to write an rspec expectation for equality when you >> get a BigDecimal back. I see that "big_decimal_variable.should == 123.23" >> doesn''t work as the ruby BigDecimal comparison (via ==) to the same Float >> value gives false (not true as you''d expect). >> > > How about bd.to_s.should == 123.23.to_s ? > > ///ark > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090111/6426fcae/attachment.html>
David Chelimsky
2009-Jan-11 14:21 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
On Sun, Jan 11, 2009 at 4:05 AM, Greg Hauptmann <greg.hauptmann.ruby at gmail.com> wrote:> I''ve gone with the following > ai.amount.should == BigDecimal(''-323.03'') > However I''m still a bit surprised that Ruby itself does allow a good "==" > test between a Float and a BigDecimal. Perhaps there''s a reason that I''m > missing?Very telling is this:>> require ''bigdecimal''=> true>> BigDecimal.new(3333333.0) == 3333333.0TypeError: can''t convert Float into String from (irb):4:in `new'' from (irb):4 As for why, I think you''ll get some good insights if you post the ruby-lang mailing list, but I can take shot. BigDecimal has explicit precision. Float does not. Imagine the developer at the bank explaining that the thousands of dollars discrepancy last year was due to an average miscalculation of 0.00005 per transaction because sometimes the code used BigDecimal, and sometimes it used Float. Personally, I think this seeming annoyance is actually a good thing. FWIW, David> > On Sun, Jan 11, 2009 at 7:23 PM, Mark Wilden <mark at mwilden.com> wrote: >> >> On Sun, Jan 11, 2009 at 12:17 AM, Greg Hauptmann >> <greg.hauptmann.ruby at gmail.com> wrote: >>> >>> Any suggestions on how to write an rspec expectation for equality when >>> you get a BigDecimal back. I see that "big_decimal_variable.should =>>> 123.23" doesn''t work as the ruby BigDecimal comparison (via ==) to the same >>> Float value gives false (not true as you''d expect). >> >> How about bd.to_s.should == 123.23.to_s ? >> >> ///ark
Rick DeNatale
2009-Jan-11 18:53 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
On Sun, Jan 11, 2009 at 9:21 AM, David Chelimsky <dchelimsky at gmail.com>wrote:> On Sun, Jan 11, 2009 at 4:05 AM, Greg Hauptmann > <greg.hauptmann.ruby at gmail.com> wrote: > > I''ve gone with the following > > ai.amount.should == BigDecimal(''-323.03'') > > However I''m still a bit surprised that Ruby itself does allow a good "==" > > test between a Float and a BigDecimal. Perhaps there''s a reason that I''m > > missing? > > Very telling is this: > > >> require ''bigdecimal'' > => true > >> BigDecimal.new(3333333.0) == 3333333.0 > TypeError: can''t convert Float into String > from (irb):4:in `new'' > from (irb):4 > > As for why, I think you''ll get some good insights if you post the > ruby-lang mailing list, but I can take shot. > > BigDecimal has explicit precision. Float does not. Imagine the > developer at the bank explaining that the thousands of dollars > discrepancy last year was due to an average miscalculation of 0.00005 > per transaction because sometimes the code used BigDecimal, and > sometimes it used Float. >Even more telling is this: irb(main):001:0> 1.0 / 3.0 => 0.333333333333333 irb(main):002:0> (1.0 / 3.00) == 0.333333333333333 => false This has little to do with rspec or Ruby, and everything to do with floats. Floats are approximations, it''s a mistake to thing of them as equivalent to the mathematical concept of real numbers, or even rational numbers. There are several issues here including 1. Floats are not infinite precision, they have a fixed number of bits or digits, this means that in-between any two consecutive real number which CAN be represented by a float, there are an infinite number of reals which cannot. 2. As is the case in decimal fractions, where some rational numbers such as 1/3 cannot be represented without an infinite number of decimal digits, there are similar values dependent on the base used for the float representation. There''s a whole branch of computer science, Numerical Analysis, comprised in large part of understanding how Floats differ from the mathematical ideal. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090111/2c6c29ee/attachment-0001.html>
Greg Hauptmann
2009-Jan-11 20:33 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
it would be nice in one''s project if you could basically say "use BigDecimal wherever you normally would have used a float", just to get the benefit but maintain ease of coding/readability etc - anyone know if this is possible? Would it be enough to override Float''s initializer and return a BigDecimal instead? On Mon, Jan 12, 2009 at 4:53 AM, Rick DeNatale <rick.denatale at gmail.com>wrote:> On Sun, Jan 11, 2009 at 9:21 AM, David Chelimsky <dchelimsky at gmail.com>wrote: > >> On Sun, Jan 11, 2009 at 4:05 AM, Greg Hauptmann >> <greg.hauptmann.ruby at gmail.com> wrote: >> > I''ve gone with the following >> > ai.amount.should == BigDecimal(''-323.03'') >> > However I''m still a bit surprised that Ruby itself does allow a good >> "==" >> > test between a Float and a BigDecimal. Perhaps there''s a reason that >> I''m >> > missing? >> >> Very telling is this: >> >> >> require ''bigdecimal'' >> => true >> >> BigDecimal.new(3333333.0) == 3333333.0 >> TypeError: can''t convert Float into String >> from (irb):4:in `new'' >> from (irb):4 >> >> As for why, I think you''ll get some good insights if you post the >> ruby-lang mailing list, but I can take shot. >> >> BigDecimal has explicit precision. Float does not. Imagine the >> developer at the bank explaining that the thousands of dollars >> discrepancy last year was due to an average miscalculation of 0.00005 >> per transaction because sometimes the code used BigDecimal, and >> sometimes it used Float. >> > > Even more telling is this: > irb(main):001:0> 1.0 / 3.0 > => 0.333333333333333 > irb(main):002:0> (1.0 / 3.00) == 0.333333333333333 > => false > > This has little to do with rspec or Ruby, and everything to do with floats. > > Floats are approximations, it''s a mistake to thing of them as equivalent to > the mathematical concept of real numbers, or even rational numbers. There > are several issues here including > > 1. Floats are not infinite precision, they have a fixed number of bits or > digits, this means that in-between any two consecutive real number which CAN > be represented by a float, there are an infinite number of reals which > cannot. > > 2. As is the case in decimal fractions, where some rational numbers such as > 1/3 cannot be represented without an infinite number of decimal digits, > there are similar values dependent on the base used for the float > representation. > > There''s a whole branch of computer science, Numerical Analysis, comprised > in large part of understanding how Floats differ from the mathematical > ideal. > > > -- > Rick DeNatale > > Blog: http://talklikeaduck.denhaven2.com/ > Twitter: http://twitter.com/RickDeNatale > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Greg http://blog.gregnet.org/ -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090112/c6c7d078/attachment.html>
MaurĂcio Linhares
2009-Jan-11 20:45 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
This is a very bad idea, as you can break the whole runtime by doing this, as many internal classes use floating point math. You would also slow the world down, as operations using BigDecimals are some order of magnitude slower than pure floating point math. - Maur?cio Linhares http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ (en) On Sun, Jan 11, 2009 at 6:33 PM, Greg Hauptmann <greg.hauptmann.ruby at gmail.com> wrote:> it would be nice in one''s project if you could basically say "use > BigDecimal wherever you normally would have used a float", just to get the > benefit but maintain ease of coding/readability etc - anyone know if this is > possible? Would it be enough to override Float''s initializer and return a > BigDecimal instead? > > > On Mon, Jan 12, 2009 at 4:53 AM, Rick DeNatale <rick.denatale at gmail.com> > wrote: >> >> On Sun, Jan 11, 2009 at 9:21 AM, David Chelimsky <dchelimsky at gmail.com> >> wrote: >>> >>> On Sun, Jan 11, 2009 at 4:05 AM, Greg Hauptmann >>> <greg.hauptmann.ruby at gmail.com> wrote: >>> > I''ve gone with the following >>> > ai.amount.should == BigDecimal(''-323.03'') >>> > However I''m still a bit surprised that Ruby itself does allow a good >>> > "==" >>> > test between a Float and a BigDecimal. Perhaps there''s a reason that >>> > I''m >>> > missing? >>> >>> Very telling is this: >>> >>> >> require ''bigdecimal'' >>> => true >>> >> BigDecimal.new(3333333.0) == 3333333.0 >>> TypeError: can''t convert Float into String >>> from (irb):4:in `new'' >>> from (irb):4 >>> >>> As for why, I think you''ll get some good insights if you post the >>> ruby-lang mailing list, but I can take shot. >>> >>> BigDecimal has explicit precision. Float does not. Imagine the >>> developer at the bank explaining that the thousands of dollars >>> discrepancy last year was due to an average miscalculation of 0.00005 >>> per transaction because sometimes the code used BigDecimal, and >>> sometimes it used Float. >> >> Even more telling is this: >> irb(main):001:0> 1.0 / 3.0 >> => 0.333333333333333 >> irb(main):002:0> (1.0 / 3.00) == 0.333333333333333 >> => false >> >> This has little to do with rspec or Ruby, and everything to do with >> floats. >> >> Floats are approximations, it''s a mistake to thing of them as equivalent >> to the mathematical concept of real numbers, or even rational numbers. There >> are several issues here including >> >> 1. Floats are not infinite precision, they have a fixed number of bits or >> digits, this means that in-between any two consecutive real number which CAN >> be represented by a float, there are an infinite number of reals which >> cannot. >> >> 2. As is the case in decimal fractions, where some rational numbers such >> as 1/3 cannot be represented without an infinite number of decimal digits, >> there are similar values dependent on the base used for the float >> representation. >> >> There''s a whole branch of computer science, Numerical Analysis, comprised >> in large part of understanding how Floats differ from the mathematical >> ideal. >> >> >> -- >> Rick DeNatale >> >> Blog: http://talklikeaduck.denhaven2.com/ >> Twitter: http://twitter.com/RickDeNatale >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users > > > > -- > Greg > http://blog.gregnet.org/ > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Tero Tilus
2009-Jan-11 21:31 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
2009-01-11 18:17, Greg Hauptmann:> Any suggestions on how to write an rspec expectation for equality when you > get a BigDecimal back. I see that "big_decimal_variable.should => 123.23"If you register keywords "comparison" and "float", you should train yourself to cry out "delta" without even thinking. ;) Would this work for you? big_decimal_variable.should be_close(123.23, 0.005) -- Tero Tilus ## 050 3635 235 ## http://tero.tilus.net/
Mark Wilden
2009-Jan-11 22:06 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
On Sun, Jan 11, 2009 at 12:17 AM, Greg Hauptmann < greg.hauptmann.ruby at gmail.com> wrote:> Any suggestions on how to write an rspec expectation for equality when you > get a BigDecimal back. I see that "big_decimal_variable.should == 123.23" > doesn''t work as the ruby BigDecimal comparison (via ==) to the same Float > value gives false (not true as you''d expect). >Noting there are two decimal places in your data, I might suggest using the Money plugin. ///ark -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090111/1d9b0159/attachment.html>
Greg Hauptmann
2009-Jan-11 22:36 UTC
[rspec-users] Why can not a BigDecimal be compared to a Float via "==". How should I handle this???
ok - thanks - seems like if one remembers to use "BigDecimal(''10.1'')", then instead of 10.1 in your code you should be ok then. On Mon, Jan 12, 2009 at 6:45 AM, Maur?cio Linhares < mauricio.linhares at gmail.com> wrote:> This is a very bad idea, as you can break the whole runtime by doing > this, as many internal classes use floating point math. You would also > slow the world down, as operations using BigDecimals are some order of > magnitude slower than pure floating point math. > > - > Maur?cio Linhares > http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ (en) > > > > On Sun, Jan 11, 2009 at 6:33 PM, Greg Hauptmann > <greg.hauptmann.ruby at gmail.com> wrote: > > it would be nice in one''s project if you could basically say "use > > BigDecimal wherever you normally would have used a float", just to get > the > > benefit but maintain ease of coding/readability etc - anyone know if this > is > > possible? Would it be enough to override Float''s initializer and return > a > > BigDecimal instead? > > > > > > On Mon, Jan 12, 2009 at 4:53 AM, Rick DeNatale <rick.denatale at gmail.com> > > wrote: > >> > >> On Sun, Jan 11, 2009 at 9:21 AM, David Chelimsky <dchelimsky at gmail.com> > >> wrote: > >>> > >>> On Sun, Jan 11, 2009 at 4:05 AM, Greg Hauptmann > >>> <greg.hauptmann.ruby at gmail.com> wrote: > >>> > I''ve gone with the following > >>> > ai.amount.should == BigDecimal(''-323.03'') > >>> > However I''m still a bit surprised that Ruby itself does allow a good > >>> > "==" > >>> > test between a Float and a BigDecimal. Perhaps there''s a reason that > >>> > I''m > >>> > missing? > >>> > >>> Very telling is this: > >>> > >>> >> require ''bigdecimal'' > >>> => true > >>> >> BigDecimal.new(3333333.0) == 3333333.0 > >>> TypeError: can''t convert Float into String > >>> from (irb):4:in `new'' > >>> from (irb):4 > >>> > >>> As for why, I think you''ll get some good insights if you post the > >>> ruby-lang mailing list, but I can take shot. > >>> > >>> BigDecimal has explicit precision. Float does not. Imagine the > >>> developer at the bank explaining that the thousands of dollars > >>> discrepancy last year was due to an average miscalculation of 0.00005 > >>> per transaction because sometimes the code used BigDecimal, and > >>> sometimes it used Float. > >> > >> Even more telling is this: > >> irb(main):001:0> 1.0 / 3.0 > >> => 0.333333333333333 > >> irb(main):002:0> (1.0 / 3.00) == 0.333333333333333 > >> => false > >> > >> This has little to do with rspec or Ruby, and everything to do with > >> floats. > >> > >> Floats are approximations, it''s a mistake to thing of them as equivalent > >> to the mathematical concept of real numbers, or even rational numbers. > There > >> are several issues here including > >> > >> 1. Floats are not infinite precision, they have a fixed number of bits > or > >> digits, this means that in-between any two consecutive real number which > CAN > >> be represented by a float, there are an infinite number of reals which > >> cannot. > >> > >> 2. As is the case in decimal fractions, where some rational numbers such > >> as 1/3 cannot be represented without an infinite number of decimal > digits, > >> there are similar values dependent on the base used for the float > >> representation. > >> > >> There''s a whole branch of computer science, Numerical Analysis, > comprised > >> in large part of understanding how Floats differ from the mathematical > >> ideal. > >> > >> > >> -- > >> Rick DeNatale > >> > >> Blog: http://talklikeaduck.denhaven2.com/ > >> Twitter: http://twitter.com/RickDeNatale > >> > >> _______________________________________________ > >> rspec-users mailing list > >> rspec-users at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/rspec-users > > > > > > > > -- > > Greg > > http://blog.gregnet.org/ > > > > > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Greg http://blog.gregnet.org/ -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090112/a905be4e/attachment-0001.html>