home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / MONEY / MONEY.H < prev    next >
C/C++ Source or Header  |  1992-12-17  |  11KB  |  396 lines

  1. /* @(#) money.h          Copymiddle 1991 Adolfo Di Mare  */
  2. /*                                                       */
  3. /*            Yet Another Money C++ Class                */
  4. /*                                                       */
  5. /*   Use freely but acknowledge author and publication.  */
  6. /*    DO NOT SELL IT. The author reserves all rigths!    */
  7.  
  8. /*                               BITNET: adimare@UCRVM2  */
  9.  
  10. /* Compiler:                           Borland C++ v 2.0 */
  11. /*                          [should work with Turbo C++] */
  12.  
  13.  
  14. #ifndef _money_h
  15. #define _money_h
  16.  
  17. extern "C" {     // avoid type clashes with the C library
  18.     #include <math.h>    /* floor() */
  19.     #include <float.h>   /* DBL_DIG */
  20. }
  21.  
  22. #ifndef MONEY_DECIMALS       /* number of decimals in */
  23. #define MONEY_DECIMALS  2    /*   any money quantity  */
  24. #endif                       /* don't use parentesis! */
  25.  
  26. #define __VAL(n)  n               /* 1 level indirection */
  27. #define TENPOW(n) __VAL(1.0e##n)  /* Trick to yield 10^n */
  28.  
  29.  
  30. #define MONEY_DIG   DBL_DIG
  31.  
  32.  
  33. class money {
  34. public:
  35.  
  36.     static int    decimals() { return MONEY_DECIMALS;     }
  37.     static int    digits()   { return MONEY_DIG; }
  38.     static double SCALE()
  39.         { return TENPOW(MONEY_DECIMALS); }
  40.  
  41.     money();              // do nothing constructor
  42.     money(double);        // constructor from double
  43.     money(const money&);  // copy constructor
  44.  
  45.     money& operator= (const money&);  // copy operator
  46.     money& operator= (double);        // copy from double
  47.     operator double() const;          // convert to double
  48.  
  49.     int  OK()   const;  // check money's invariant
  50.     void FIX();         // get rid of unwanted decimals
  51.  
  52.  
  53.     friend money  operator + (const money&, const money&);
  54.     friend money  operator + (double,       const money&);
  55.     friend money  operator + (const money&, double);
  56.     friend money  operator - (const money&, const money&);
  57.     friend money  operator - (double,       const money&);
  58.     friend money  operator - (const money&, double);
  59.  
  60.     friend money  operator*  (const money&, double);
  61.     friend money  operator*  (double,       const money&);
  62.     friend double operator/  (const money&, const money&);
  63.     friend money  operator/  (const money&, double);
  64.     friend money  operator%  (const money&, const money&);
  65.  
  66.     // money  * money  is NOT valid
  67.     // double / money  is INVALID
  68.  
  69.     friend int operator == (const money&, const money&);
  70.     friend int operator != (const money&, const money&);
  71.     friend int operator <  (const money&, const money&);
  72.     friend int operator >  (const money&, const money&);
  73.     friend int operator <= (const money&, const money&);
  74.     friend int operator >= (const money&, const money&);
  75.  
  76.     friend int operator == (const money&, double);
  77.     friend int operator != (const money&, double);
  78.     friend int operator <  (const money&, double);
  79.     friend int operator >  (const money&, double);
  80.     friend int operator <= (const money&, double);
  81.     friend int operator >= (const money&, double);
  82.  
  83.     friend int operator == (double, const money&);
  84.     friend int operator != (double, const money&);
  85.     friend int operator <  (double, const money&);
  86.     friend int operator >  (double, const money&);
  87.     friend int operator <= (double, const money&);
  88.     friend int operator >= (double, const money&);
  89.  
  90.     money& operator += (const money&);
  91.     money& operator += (double);
  92.     money& operator -= (const money&);
  93.     money& operator -= (double);
  94.  
  95.     money& operator *= (double);
  96.     money& operator /= (double);
  97.  
  98.     friend money  operator+ (const money&);
  99.     friend money  operator- (const money&);
  100.     money& operator++();     // prefix
  101.     money& operator--();
  102.     money& operator++(int);  // postfix
  103.     money& operator--(int);
  104.     friend int    operator! (const money&);
  105.  
  106.     friend money abs(const money&);
  107.     friend money flatten(
  108.          const money& m,
  109.          double cents=0.25, int rounding = 1 /* TRUE */);
  110.  
  111. protected:         // let users change the class behaviour
  112.     double m_money;
  113. };
  114.  
  115. // Constructors && assignment
  116. inline money::money() {
  117. // do nothing constructor, for efficiency
  118. }
  119. inline money::money(double d) {
  120. // construct from double
  121.     m_money = d*SCALE();
  122.     FIX();
  123. }
  124. inline money::money(const money& m) {
  125. // copy constructor
  126.     m_money = m.m_money;
  127. }
  128.  
  129. inline money& money::operator= (const money& m) {
  130. // copy operator
  131.     m_money = m.m_money;
  132.     return *this;
  133. }
  134. inline money& money::operator= (double d) {
  135. // assign from double
  136.     m_money = d*SCALE();
  137.     FIX();
  138.     return *this;
  139. }
  140. inline money::operator double() const {
  141. // convert to double
  142.     return m_money / SCALE();
  143. }
  144.  
  145. inline int money::OK() const {
  146. // Returns TRUE (1) when the quantity stored
  147. // in *this really corresponds to a money
  148. // quantity.
  149.  
  150.     money temp;
  151.     temp.m_money = m_money;
  152.     temp.FIX();
  153.     return (
  154.         ( temp.m_money == m_money )
  155.           &&
  156.         ( fabs(m_money) < (TENPOW(DBL_DIG) / SCALE()) )
  157.     );
  158. }
  159.  
  160. inline void money::FIX() {
  161. // Deletes all decimals digits beyond
  162. // the MONEY_DECIMALS decimal place.
  163. // - If the value is out of range, FIX
  164. //   won't fix it.
  165.     m_money =
  166.         (m_money > 0.0
  167.             ?
  168.                 floor(
  169.                     m_money
  170.                      #ifdef MONEY_ROUNDING
  171.                         + 0.5 // 0.49 is also an option...
  172.                      #endif
  173.                  )
  174.             :
  175.                 ceil(
  176.                     m_money
  177.                      #ifdef MONEY_ROUNDING
  178.                         - 0.5
  179.                      #endif
  180.                  )
  181.         );
  182. }
  183.  
  184. // add
  185. inline money operator+ (const money& m, const money& mm) {
  186.     money temp;    // don't mult*SCALE()
  187.     temp.m_money = m.m_money + mm.m_money;
  188.     return temp;
  189. }
  190. inline money operator+ (double d, const money& m) {
  191.     return (money(d)+m);
  192. }
  193. inline money operator+ (const money& m, double d) {
  194.     return (m+money(d));
  195. }
  196.  
  197. // substract
  198. inline money operator- (const money& m, const money& mm) {
  199.     money temp;
  200.     temp.m_money = m.m_money - mm.m_money;
  201.     return temp;
  202. }
  203. inline money operator- (double d, const money& m) {
  204.     return (money(d)-m);
  205. }
  206. inline money operator- (const money& m, double d) {
  207.     return (m-money(d));
  208. }
  209.  
  210. // multiply
  211. inline money operator* (const money& m, double d) {
  212.     money temp;
  213.     temp.m_money = m.m_money * d; // don't mult by SCALE()
  214.     temp.FIX();    // this could be delayed...
  215.     return temp;
  216. }
  217. inline money operator* (double d, const money& m) {
  218.     return (m*d);
  219. }
  220.  
  221. // divide
  222. inline double operator/ (const money& m, const money& mm) {
  223.     return m.m_money / mm.m_money;
  224. }
  225. inline money  operator/ (const money& m, double d) {
  226.     money temp;
  227.     temp.m_money = m.m_money / d;
  228.     temp.FIX();    // this could be delayed...
  229.     return temp;
  230. }
  231. inline money operator%  (const money& m, const money& mm) {
  232.     money temp;
  233.     temp.m_money = fmod(m.m_money, mm.m_money);
  234.     temp.FIX();    // this could be delayed...
  235.     return temp;
  236. }
  237.  
  238. // compare
  239. inline int operator  == (const money& m, const money& mm) {
  240.     return m.m_money ==  mm.m_money;
  241. }
  242. inline int operator  != (const money& m, const money& mm) {
  243.     return m.m_money !=  mm.m_money;
  244. }
  245. inline int operator  <  (const money& m, const money& mm) {
  246.     return m.m_money <   mm.m_money;
  247. }
  248. inline int operator  >  (const money& m, const money& mm) {
  249.     return m.m_money >   mm.m_money;
  250. }
  251. inline int operator  <= (const money& m, const money& mm) {
  252.     return m.m_money <=  mm.m_money;
  253. }
  254. inline int operator  >= (const money& m, const money& mm) {
  255.     return m.m_money >=  mm.m_money;
  256. }
  257.  
  258. inline int operator  == (const money& m, double mm) {
  259.     return m.m_money == mm;
  260. //  return m.m_money == (money)mm;  // take a pick !!!
  261. /*
  262.     A decission that you should make is whether this
  263.     equality comparison requires the double quantity
  264.     to  be  promoted  to  a money item.  The  direct
  265.     comparison   is   more   transparent,   so it is
  266.     prefered in here.
  267. */
  268. }
  269. inline int operator  != (const money& m, double mm) {
  270.     return !(m == mm);
  271. }
  272. inline int operator  <  (const money& m, double mm) {
  273.     return m.m_money <  mm;
  274. }
  275. inline int operator  >  (const money& m, double mm) {
  276.     return m.m_money >  mm;
  277. }
  278. inline int operator  <= (const money& m, double mm) {
  279.     return m.m_money <= mm;
  280. }
  281. inline int operator  >= (const money& m, double mm) {
  282.     return m.m_money >= mm;
  283. }
  284.  
  285. inline int operator  == (double m, const money& mm) {
  286.     return  (mm == m);
  287. }
  288. inline int operator  != (double m, const money& mm) {
  289.     return !(mm == m);
  290. }
  291. inline int operator  <  (double m, const money& mm) {
  292.     return         m <  mm.m_money;
  293. }
  294. inline int operator  >  (double m, const money& mm) {
  295.     return         m >  mm.m_money;
  296. }
  297. inline int operator  <= (double m, const money& mm) {
  298.     return         m <= mm.m_money;
  299. }
  300. inline int operator  >= (double m, const money& mm) {
  301.     return         m >= mm.m_money;
  302. }
  303.  
  304. inline money& money::operator += (const money& m) {
  305.     m_money += m.m_money;
  306.     return *this;
  307. }
  308. inline money& money::operator += (double d) {
  309.     m_money += d*SCALE();
  310.     FIX();
  311.     return *this;
  312. }
  313. inline money& money::operator -= (const money& m) {
  314.     m_money -= m.m_money;
  315.     return *this;
  316. }
  317. inline money& money::operator -= (double d) {
  318.     m_money -= d*SCALE();
  319.     FIX();
  320.     return *this;
  321. }
  322. inline money& money::operator *= (double d) {
  323.     m_money *= d;
  324.     FIX();
  325.     return *this;
  326. }
  327. inline money& money::operator /= (double d) {
  328.     m_money /= d;
  329.     FIX();
  330.     return *this;
  331. }
  332.  
  333. // unary op's
  334. inline money operator+(const money& m) {
  335.     return m;
  336. }
  337. inline money operator-(const money& m) {
  338.     money temp;
  339.     temp.m_money = -m.m_money;
  340.     return temp;
  341. }
  342. inline money& money::operator++() {
  343.     m_money += SCALE();
  344.     #if (MONEY_DECIMALS<0)
  345.         FIX(); // avoid problems because of
  346.     #endif     // the representation of 10^-n
  347.     return *this;
  348. }
  349. inline money& money::operator--() {
  350.     m_money -= SCALE();
  351.     #if (MONEY_DECIMALS<0)
  352.         FIX();
  353.     #endif
  354.     return *this;
  355. }
  356.  
  357. inline money& money::operator++(int) {
  358.     return ++(*this);
  359. }
  360.  
  361. inline money& money::operator--(int) {
  362.     return --(*this);
  363. }
  364. inline int operator!(const money& m) {
  365.     return m.m_money == 0.0;
  366. }
  367.  
  368. inline money abs(const money& m) {
  369.     money temp;
  370.     temp.m_money = fabs(m.m_money);
  371.     return temp;
  372. }
  373.  
  374. money flatten(const money& m, double cents, int rounding) {
  375. // Returns a money data item where the cents are
  376. // rounded modulo "cents". In this way cents can
  377. // be stripped of money items when the currency
  378. // does not have all the coins required to pay
  379. // every posible quantity.
  380.     money temp;
  381.     double c = floor(fabs(cents*money::SCALE())); // cents
  382.     double r = fmod(m.m_money, c);            // remainder
  383.     temp.m_money =
  384.         (!rounding || (2.0* r <= c)
  385.             ? m.m_money - r
  386.             : m.m_money - r + c
  387.         );
  388.     return temp;
  389. }
  390.  
  391. /* Avoid name space overcrowding */
  392. #undef __VAL
  393. #undef TENPOW /* jic: Just In Case! */
  394.  
  395. #endif  /* _money_h */
  396.