money comparison

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

money comparison

Matt Fair
I'm wondering if in money.cpp for bool operator==(const Money& m1, const Money& m2), the comparison between two double values should not be a straight ==.  But instead there should be a is_equal function with an epselon to compare the two values.  Because due to how the system stores numbers, double values can be shifted slightly when operations are performed on them.  I'm having problems comparing two money values because of several math operations, they aren't quite the same.

Given:
bool is_equal(double d1, double d2) 
{
        if(abs(d1-d2)<epsilon)
                return true;
        return false;
}

Where epsilon could be defined by the currency precision.

I would suggest:
return m1.value() == m2.value();

be changed to:
return is_equal(m1.value(), m2.value());

See the following links for more info:
http://www.cplusplus.com/forum/articles/3827/
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

Thanks,
Matt

------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: money comparison

Matt Fair
I noticed that there are already functions that do exactly what I described. Here is a modification to money.cpp that I think would make sense:

Index: money.cpp
===================================================================
--- money.cpp    (revision 17937)
+++ money.cpp    (working copy)
 
@@ -103,17 +105,7 @@
 
     bool operator==(const Money& m1, const Money& m2) {
         if (m1.currency() == m2.currency()) {
-            return m1.value() == m2.value();
-        } else if (Money::conversionType == Money::BaseCurrencyConversion) {
-            Money tmp1 = m1;
-            convertToBase(tmp1);
-            Money tmp2 = m2;
-            convertToBase(tmp2);
-            return tmp1 == tmp2;
-        } else if (Money::conversionType == Money::AutomatedConversion) {
-            Money tmp = m2;
-            convertTo(tmp, m1.currency());
-            return m1 == tmp;
+                        return close_enough(m1, m2);
         } else {
             QL_FAIL("currency mismatch and no conversion specified");
         }

Matt


On Fri, Sep 2, 2011 at 2:22 PM, Matt Fair <[hidden email]> wrote:
I'm wondering if in money.cpp for bool operator==(const Money& m1, const Money& m2), the comparison between two double values should not be a straight ==.  But instead there should be a is_equal function with an epselon to compare the two values.  Because due to how the system stores numbers, double values can be shifted slightly when operations are performed on them.  I'm having problems comparing two money values because of several math operations, they aren't quite the same.

Given:
bool is_equal(double d1, double d2) 
{
        if(abs(d1-d2)<epsilon)
                return true;
        return false;
}

Where epsilon could be defined by the currency precision.

I would suggest:
return m1.value() == m2.value();

be changed to:
return is_equal(m1.value(), m2.value());

See the following links for more info:
http://www.cplusplus.com/forum/articles/3827/
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

Thanks,
Matt


------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: money comparison

Luigi Ballabio

Matt,
        both behaviors are provided on purpose, same as for floats.  One can
use m1 == m2 for exact comparison, and close_enough for fuzzy comparison
including rounding.

Regards,
        Luigi


On Fri, 2011-09-02 at 16:36 -0600, Matt Fair wrote:

> I noticed that there are already functions that do exactly what I
> described. Here is a modification to money.cpp that I think would make
> sense:
>
> Index: money.cpp
> ===================================================================
> --- money.cpp    (revision 17937)
> +++ money.cpp    (working copy)
>  
> @@ -103,17 +105,7 @@
>  
>      bool operator==(const Money& m1, const Money& m2) {
>          if (m1.currency() == m2.currency()) {
> -            return m1.value() == m2.value();
> -        } else if (Money::conversionType ==
> Money::BaseCurrencyConversion) {
> -            Money tmp1 = m1;
> -            convertToBase(tmp1);
> -            Money tmp2 = m2;
> -            convertToBase(tmp2);
> -            return tmp1 == tmp2;
> -        } else if (Money::conversionType ==
> Money::AutomatedConversion) {
> -            Money tmp = m2;
> -            convertTo(tmp, m1.currency());
> -            return m1 == tmp;
> +                        return close_enough(m1, m2);
>          } else {
>              QL_FAIL("currency mismatch and no conversion specified");
>          }
>
> Matt
>
>
> On Fri, Sep 2, 2011 at 2:22 PM, Matt Fair <[hidden email]> wrote:
>         I'm wondering if in money.cpp for bool operator==(const Money&
>         m1, const Money& m2), the comparison between two double values
>         should not be a straight ==.  But instead there should be a
>         is_equal function with an epselon to compare the two values.
>         Because due to how the system stores numbers, double values
>         can be shifted slightly when operations are performed on them.
>         I'm having problems comparing two money values because of
>         several math operations, they aren't quite the same.
>        
>         Given:
>         bool is_equal(double d1, double d2)
>         {
>                 if(abs(d1-d2)<epsilon)
>                         return true;
>                 return false;
>         }
>        
>         Where epsilon could be defined by the currency precision.
>        
>         I would suggest:
>         return m1.value() == m2.value();
>        
>         be changed to:
>         return is_equal(m1.value(), m2.value());
>        
>         See the following links for more info:
>         http://www.cplusplus.com/forum/articles/3827/
>         http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
>        
>         Thanks,
>         Matt
>
> ------------------------------------------------------------------------------
> Special Offer -- Download ArcSight Logger for FREE!
> Finally, a world-class log management solution at an even better
> price-free! And you'll get a free "Love Thy Logs" t-shirt when you
> download Logger. Secure your free ArcSight Logger TODAY!
> http://p.sf.net/sfu/arcsisghtdev2dev
> _______________________________________________ QuantLib-dev mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-dev

--

Steinbach's Guideline for Systems Programming:
Never test for an error condition you don't know how to handle.



------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: money comparison

Matt Fair
Luigi,
I understand that you can call close_enough manually if you need to, but from an object oriented standpoint it doesn't make sense.  Is there a reason why you have both?  The only time you would get something that is equal is if you were to set the same constant value to two Money objects.  So if I have two piles of cash, one was define explicitly and the other was through mathematical operations (i.e. interest), if they are the same amount of money and I use ==, it should return true.  But that is not the behavior, == will rarely be true because of how double precision values are stored.  So comparing my two stacks of money that should be both $100 that should be equal but don't, and then for me to get the right answer, I need to go beyond the basic understanding of the object API and understand, understand it's real representation and and why there is different behaviors for different methods that should be the same to get the right answer because the equality operator isn't right.  Seems like way too much knowledge I need to know in order to use the object properly.
Matt

On Mon, Sep 5, 2011 at 8:33 AM, Luigi Ballabio <[hidden email]> wrote:

Matt,
       both behaviors are provided on purpose, same as for floats.  One can
use m1 == m2 for exact comparison, and close_enough for fuzzy comparison
including rounding.

Regards,
       Luigi


On Fri, 2011-09-02 at 16:36 -0600, Matt Fair wrote:
> I noticed that there are already functions that do exactly what I
> described. Here is a modification to money.cpp that I think would make
> sense:
>
> Index: money.cpp
> ===================================================================
> --- money.cpp    (revision 17937)
> +++ money.cpp    (working copy)
>
> @@ -103,17 +105,7 @@
>
>      bool operator==(const Money& m1, const Money& m2) {
>          if (m1.currency() == m2.currency()) {
> -            return m1.value() == m2.value();
> -        } else if (Money::conversionType ==
> Money::BaseCurrencyConversion) {
> -            Money tmp1 = m1;
> -            convertToBase(tmp1);
> -            Money tmp2 = m2;
> -            convertToBase(tmp2);
> -            return tmp1 == tmp2;
> -        } else if (Money::conversionType ==
> Money::AutomatedConversion) {
> -            Money tmp = m2;
> -            convertTo(tmp, m1.currency());
> -            return m1 == tmp;
> +                        return close_enough(m1, m2);
>          } else {
>              QL_FAIL("currency mismatch and no conversion specified");
>          }
>
> Matt
>
>
> On Fri, Sep 2, 2011 at 2:22 PM, Matt Fair <[hidden email]> wrote:
>         I'm wondering if in money.cpp for bool operator==(const Money&
>         m1, const Money& m2), the comparison between two double values
>         should not be a straight ==.  But instead there should be a
>         is_equal function with an epselon to compare the two values.
>         Because due to how the system stores numbers, double values
>         can be shifted slightly when operations are performed on them.
>         I'm having problems comparing two money values because of
>         several math operations, they aren't quite the same.
>
>         Given:
>         bool is_equal(double d1, double d2)
>         {
>                 if(abs(d1-d2)<epsilon)
>                         return true;
>                 return false;
>         }
>
>         Where epsilon could be defined by the currency precision.
>
>         I would suggest:
>         return m1.value() == m2.value();
>
>         be changed to:
>         return is_equal(m1.value(), m2.value());
>
>         See the following links for more info:
>         http://www.cplusplus.com/forum/articles/3827/
>         http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
>
>         Thanks,
>         Matt
>
> ------------------------------------------------------------------------------
> Special Offer -- Download ArcSight Logger for FREE!
> Finally, a world-class log management solution at an even better
> price-free! And you'll get a free "Love Thy Logs" t-shirt when you
> download Logger. Secure your free ArcSight Logger TODAY!
> http://p.sf.net/sfu/arcsisghtdev2dev
> _______________________________________________ QuantLib-dev mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-dev

--

Steinbach's Guideline for Systems Programming:
Never test for an error condition you don't know how to handle.




------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: money comparison

Luigi Ballabio
On Mon, 2011-09-05 at 09:31 -0600, Matt Fair wrote:
> Luigi,
> I understand that you can call close_enough manually if you need to,
> but from an object oriented standpoint it doesn't make sense.  Is
> there a reason why you have both?

It was to have the same behavior as doubles, but I see your point.
That's an implementation detail, not the behavior expected in the domain
(actually, Money shouldn't use a floating-point number at all---we
should store an integer number of cents---but that's for another time.)
I wonder if one should go all the way and compare after rounding?

Thoughts?

Luigi


--

Better to have an approximate answer to the right question than a
precise answer to the wrong question.
-- John Tukey as quoted by John Chambers



------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: money comparison

Matt Fair
I guess the real question is do you want to be able to track fractions of the currency (i.e. cents)?  If the currency goes to 2 decimal places, do you want to track to 6 or larger places?  Does that make sense in any situation?  
Should you floor (i.e. round down) anything past the decimal place of the currency?  If you want to do that, then you could store everything in an integer.  So for example  $102.38 would be stored as 10238.  That would eliminate any rounding issues and you could do a straight == of the value to do the comparison.
I don't think you ever want to round up, always down.  What are other people's thoughts on this?
Matt


On Tue, Sep 6, 2011 at 5:01 AM, Luigi Ballabio <[hidden email]> wrote:
On Mon, 2011-09-05 at 09:31 -0600, Matt Fair wrote:
> Luigi,
> I understand that you can call close_enough manually if you need to,
> but from an object oriented standpoint it doesn't make sense.  Is
> there a reason why you have both?

It was to have the same behavior as doubles, but I see your point.
That's an implementation detail, not the behavior expected in the domain
(actually, Money shouldn't use a floating-point number at all---we
should store an integer number of cents---but that's for another time.)
I wonder if one should go all the way and compare after rounding?

Thoughts?

Luigi


--

Better to have an approximate answer to the right question than a
precise answer to the wrong question.
-- John Tukey as quoted by John Chambers




------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev