lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] valyuta/001 f968298 2/4: Import currency class and u


From: Greg Chicares
Subject: [lmi-commits] [lmi] valyuta/001 f968298 2/4: Import currency class and unit test from branch valyuta/000
Date: Sat, 22 Aug 2020 11:37:09 -0400 (EDT)

branch: valyuta/001
commit f96829870de869609cf29e40b99e6f84b96b2949
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Import currency class and unit test from branch valyuta/000
---
 currency.hpp      | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 currency_test.cpp | 18 +++++++++++
 2 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/currency.hpp b/currency.hpp
index a3a3fc2..9dea3e8 100644
--- a/currency.hpp
+++ b/currency.hpp
@@ -24,6 +24,95 @@
 
 #include "config.hpp"
 
-using currency = double;
+#include "bourn_cast.hpp"
+#include "round_to.hpp"
+
+#include <cstdint>                      // int64_t
+#include <iostream>                     // ostream
+
+class currency
+{
+    using data_type = std::int64_t;
+    friend std::ostream& operator<<(std::ostream&, currency const&);
+    friend class currency_test;
+
+  public:
+    currency() = default;
+    currency(currency const&) = default;
+    ~currency() = default;
+
+    explicit currency(double d)  {m_ = from_double(d);}
+
+    currency& operator=(currency const&) = default;
+    currency& operator=(double d) {m_ = from_double(d); return *this;}
+
+    operator double() const {return to_double();}
+
+    // Is this better, with 'const&'?
+//  bool operator==(currency const& z) const {return z.m_ == m_;}
+
+    bool operator< (currency z) const {return m_ <  z.m_;}
+    bool operator<=(currency z) const {return m_ <= z.m_;}
+    bool operator==(currency z) const {return m_ == z.m_;}
+    bool operator!=(currency z) const {return m_ != z.m_;}
+    bool operator> (currency z) const {return m_ >  z.m_;}
+    bool operator>=(currency z) const {return m_ >= z.m_;}
+
+    bool operator< (double d) const {return to_double() <  d;}
+    bool operator<=(double d) const {return to_double() <= d;}
+    bool operator==(double d) const {return to_double() == d;}
+    bool operator!=(double d) const {return to_double() != d;}
+    bool operator> (double d) const {return to_double() >  d;}
+    bool operator>=(double d) const {return to_double() >= d;}
+
+    // Is this the ideal signature for this operator?
+//  currency operator-() const {return currency(-m_);}
+//  currency& operator-() {m_ = -m_; return *this;}
+
+    currency& operator+=(currency z) {m_ += z.m_; return *this;}
+    currency& operator-=(currency z) {m_ -= z.m_; return *this;}
+    // NOPE!
+//  currency& operator*=(currency z) {m_ *= z.m_; return *this;}
+
+    currency& operator+=(double z) {m_ += from_double(z); return *this;}
+    currency& operator-=(double z) {m_ -= from_double(z); return *this;}
+    // NOPE!
+//  currency& operator*=(double z) {m_ *= from_double(z); return *this;}
+    // Check result range (and avoid multiplying by 100/100):
+//  currency& operator*=(double z) {m_ = bourn_cast<data_type>(100.0 * 
to_double() * z); return *this;}
+    // Far too permissive:
+//  currency& operator*=(double z) {m_ = static_cast<data_type>(100.0 * 
to_double() * z); return *this;}
+    double operator*=(double z) {return to_double() * z;}
+
+  private:
+    // Want something just slightly more permissive:
+//  data_type from_double(double d) const {return bourn_cast<data_type>(100.0 
* d);}
+    // Far too permissive:
+//  data_type from_double(double d) const {return static_cast<data_type>(100.0 
* d);}
+    // ...and a bit insidious:
+//  data_type from_double(double d) const {return 
static_cast<data_type>(100.000000000001 * d);}
+    // ...less bad:
+    data_type from_double(double d) const {return round(100.0 * d);}
+    double to_double() const {return bourn_cast<double>(m_) / 100.0;}
+
+    data_type round(double d) const
+        {
+        static round_to<double> const r(0, r_to_nearest);
+        return static_cast<data_type>(r(d));
+        }
+
+    data_type m_ = {0};
+};
+
+inline currency operator+(currency lhs, double rhs) {return lhs += 
currency(rhs);}
+inline currency operator-(currency lhs, double rhs) {return lhs -= 
currency(rhs);}
+//inline currency operator*(currency lhs, double rhs) {return lhs *= 
currency(rhs);}
+inline double operator*(currency lhs, double rhs) {return lhs *= 
currency(rhs);}
+
+inline std::ostream& operator<<(std::ostream& os, currency const& c)
+{
+//  return os << c.m_ << ' ' << c.to_double();
+    return os << c.to_double();
+}
 
 #endif // currency_hpp
diff --git a/currency_test.cpp b/currency_test.cpp
index 9920b13..e7af97f 100644
--- a/currency_test.cpp
+++ b/currency_test.cpp
@@ -41,6 +41,24 @@ void currency_test::test()
 
 void currency_test::test_something()
 {
+    currency a0;
+    std::cout << a0 << std::endl;
+    BOOST_TEST(0.00 == a0.operator double());
+    BOOST_TEST(   0 == a0.m_);
+
+// Figure out what to do about this:
+//  currency a1(3.14);
+
+    currency a1(3.25);
+    BOOST_TEST(3.25 == a1.operator double());
+    BOOST_TEST( 325 == a1.m_);
+    BOOST_TEST(   0 == a1 * a0);
+    a1 += a1;
+    BOOST_TEST(6.50 == a1.operator double());
+    BOOST_TEST( 650 == a1.m_);
+    a1 *= a0;
+    BOOST_TEST(0.00 == a1.operator double());
+    BOOST_TEST(   0 == a1.m_);
 }
 
 int test_main(int, char*[])



reply via email to

[Prev in Thread] Current Thread [Next in Thread]