在C#和Java中都有存在decimal类似的十进制数字,C++中尚未发现,春节假期忙里抽闲写了一个玩玩,时间紧迫没有测试,只能保证编译通过。抛砖引玉,欢迎大家多提建议

当前缺陷:

1. 除法功能没有实现

2. 没有测试

3. 代码比较乱没有重构,部分命名不规范

4. 算法效率比较低

老规矩直接上代码:

VS 2010 工程

http://files.cnblogs.com/files/GhostZCH/CDecimalProject.rar

h文件

 1 #ifndef _CDECIMAL_H_
 2 #define _CDECIMAL_H_
 3 
 4 #include <vector>
 5 #include <string>
 6 
 7 using namespace std;
 8 
 9 typedef char INT8;
10 typedef vector<INT8> LONG_INT;
11 
12 typedef enum 
13 {
14     SIGN_NAGETIVE = -1,
15     SIGN_POSTIVE  =  1
16 }SIGN_ENUM;
17 
18 class CDecimal
19 {
20 public:
21     CDecimal();
22     CDecimal(const CDecimal &Other);
23     CDecimal(const string &strNumber); // 建议使用
24     CDecimal(const long long int iSourceNumber); // 建议使用
25     CDecimal(const long double iSourceNumber);
26     
27     CDecimal operator + (const CDecimal &other);
28     CDecimal operator - (const CDecimal &other);
29     CDecimal operator * (const CDecimal &other);
30     CDecimal operator / (const CDecimal &other);
31 
32     bool operator == (const CDecimal &other);
33     bool operator > (const CDecimal &other);
34     bool operator < (const CDecimal &other);
35 
36     size_t IntigerLenth();
37     size_t DecamalLenth();
38 
39     SIGN_ENUM Sign();
40     bool IsPostive();
41 
42     string ToString();
43     string ToString(size_t uDecimalLenth);
44     
45     ~CDecimal();
46 
47 public:
48     static CDecimal& Ceil(CDecimal& dDecimal);
49     static CDecimal& Floor(CDecimal& dDecimal);
50     static CDecimal& Round(CDecimal& dDecimal);
51 
52 
53 private:
54     void Init(bool bIsToZero = false);
55 
56     bool IsStringRight(const string& strNumber, size_t& uPointPosition, SIGN_ENUM& emSign);
57     void SetDataByString(const string& strNumber, SIGN_ENUM emSign, size_t uPointPostion, LONG_INT& numIntiger, LONG_INT& numDecimal);
58 
59     bool IsAbsBigger(const CDecimal& oNumber1, const CDecimal& oNumber2);
60 
61     void AddVector(LONG_INT& vecNumberList1, LONG_INT& vecNumberList2);    // 加到第一个vector上
62     void TrimVector(LONG_INT& vecNUmberList);  // 去掉多余的 0
63     void GetObjByVector(CDecimal& oRlst, const LONG_INT& vecRlst , size_t uDecaimalCount);
64     LONG_INT GetVectorByObj(const CDecimal& oOther);
65 
66     CDecimal& InnerAdd(CDecimal& oRslt,  CDecimal& oOther);
67     CDecimal& InnerSub(CDecimal& oRslt,  CDecimal& oOther);
68     void InnerMuti(LONG_INT& vecRslt, const LONG_INT& vecThis, const LONG_INT& vecOther);
69 
70 private:
71     SIGN_ENUM m_emSign;
72     LONG_INT m_numIntiger;
73     LONG_INT m_numDecimal;
74 };
75 
76 #endif

cpp文件

  1 #include "CDecimal.h"
  2 #include <math.h>
  3 #include <sstream>
  4 
  5 const int NUM_BASE = 10; 
  6 typedef LONG_INT::iterator LongIntIterator;
  7 
  8 inline size_t Min(size_t a, size_t b)
  9 {
 10     return a > b ? b : a;
 11 }
 12 
 13 inline size_t Max(size_t a, size_t b)
 14 {
 15     return a < b ? b : a;
 16 }
 17 
 18 /************************************************************************/
 19 /*           构造析构函数                                                                                                                      */
 20 /************************************************************************/
 21 void CDecimal::Init(bool bIsToZero)
 22 {
 23     m_emSign = SIGN_POSTIVE;
 24     m_numIntiger.clear();
 25     m_numDecimal.clear();
 26 
 27     if(bIsToZero)
 28     {
 29         m_numIntiger.push_back(0);
 30     }
 31 }
 32 
 33 bool CDecimal::IsStringRight(const string& strNumber, size_t& uPointPosition, SIGN_ENUM& emSign)
 34 {
 35     if(string::npos != strNumber.find_first_not_of("-0123456789."))
 36     {
 37         return false;
 38     }
 39 
 40     // 小数点的位置和个数
 41     uPointPosition = strNumber.find_first_of('.');
 42     if(uPointPosition != string::npos && uPointPosition != strNumber.find_last_of('.'))
 43     {
 44         return false;
 45     }
 46 
 47     //负号的位置和个数
 48     size_t uSignPostion = strNumber.find_first_of('-');
 49 
 50     if(uSignPostion == string::npos)
 51     {
 52         // 不存在
 53         emSign = SIGN_POSTIVE;
 54         return true;
 55     }
 56 
 57     if(uSignPostion != strNumber.find_last_of('-'))
 58     {
 59         // 多个符号
 60         return false;
 61     }
 62 
 63     emSign = SIGN_NAGETIVE;
 64     return true;
 65 }
 66 
 67 void CDecimal::SetDataByString(const string& strNumber, SIGN_ENUM emSign, size_t uPointPostion, LONG_INT& numIntiger, LONG_INT& numDecimal)
 68 {
 69     size_t uStartPos = (uPointPostion == string::npos) ? (strNumber.length() - 1) : (uPointPostion - 1);
 70     size_t uEndPos   = (emSign == SIGN_NAGETIVE) ? 1 : 0;
 71 
 72     //整数部分
 73     for(size_t u = uStartPos; u >= uEndPos && u < strNumber.length(); --u)
 74     {
 75         numIntiger.push_back((INT8)(strNumber[u] - '0'));
 76     }
 77 
 78     //小数部分
 79     if(uPointPostion == string::npos)
 80     {
 81         return;
 82     }
 83 
 84     uStartPos = uPointPostion + 1;
 85     uEndPos   = strNumber.length() - 1;
 86     for(size_t u = uStartPos; u <= uEndPos; ++u)
 87     {
 88         numIntiger.push_back((INT8)(strNumber[u] - '0'));
 89     }
 90 }
 91 
 92 // 构造函数
 93 
 94 CDecimal::CDecimal()
 95 {
 96     Init(true);
 97 }
 98 
 99 CDecimal::CDecimal(const CDecimal &Other)
100 {
101     Init();
102     m_emSign = Other.m_emSign;
103     m_numIntiger = Other.m_numIntiger;
104     m_numDecimal = Other.m_numDecimal;
105 }
106 
107 CDecimal::CDecimal(const string &strNumber)
108 {
109     size_t uPointPosition = 0;
110     SIGN_ENUM emSign = SIGN_POSTIVE;
111 
112     if(!IsStringRight(strNumber, uPointPosition, emSign))
113     {
114         Init(true);
115         return;
116     }
117 
118     Init();
119     m_emSign = emSign;
120 
121     SetDataByString(strNumber, emSign, uPointPosition, m_numIntiger, m_numDecimal);
122 }
123 
124 CDecimal::CDecimal(const long long int iSourceNumber)
125 {
126     long long int iTmp = (iSourceNumber >= 0) ? iSourceNumber : -iSourceNumber;
127 
128     Init();
129 
130     m_emSign = (iSourceNumber >= 0) ? SIGN_POSTIVE : SIGN_NAGETIVE;
131 
132     while(0 != iTmp)
133     {
134         m_numIntiger.push_back((INT8)(iTmp % NUM_BASE));
135         iTmp /= NUM_BASE;
136     }
137 }
138 
139 CDecimal::CDecimal(const long double dSourceNumber)
140 {
141     long double dDecimalPart = 0;
142     long double dIntigerPart = dSourceNumber;
143 
144     Init();
145     if(dSourceNumber < 0)
146     {
147         m_emSign = SIGN_NAGETIVE;
148         dIntigerPart = -dIntigerPart;
149     }
150 
151     dIntigerPart = floor(dIntigerPart);
152     dDecimalPart = abs(dSourceNumber) - dIntigerPart;
153 
154     // 整数部分,每次都会floor 可以直接与0比较
155     while(dIntigerPart != 0)
156     {
157         long double dTmp = dIntigerPart;
158         dIntigerPart = floor(dIntigerPart / 10);
159         m_numIntiger.push_back((INT8)(dTmp - dIntigerPart * 10));
160     }
161 
162     // 小数部分,可能出现是循环或者丢失精度
163     while(dDecimalPart != 0)
164     {
165         dDecimalPart = dDecimalPart * 10;
166         long double dTmp = floor(dDecimalPart);
167         m_numDecimal.push_back((INT8)dTmp);
168         dDecimalPart -= dTmp;
169     }
170 }
171 
172 CDecimal::~CDecimal()
173 {
174     Init();
175 }
176 
177 /************************************************************************/
178 /*           操作符函数                                                                                                                           */
179 /************************************************************************/
180 void CDecimal::AddVector(LONG_INT& vecNumberList1, LONG_INT& vecNumberList2)
181 {
182     if(vecNumberList1.size() < vecNumberList2.size())
183     {
184         for(size_t u = 0; u < vecNumberList1.size(); ++u)
185         {
186             vecNumberList1[u] += vecNumberList2[u];
187         }
188         for(size_t u = vecNumberList1.size(); u < vecNumberList2.size(); ++u)
189         {
190             vecNumberList1.push_back(vecNumberList2[u]);
191         }
192         return;
193     }
194 
195     for(size_t u = 0; u < vecNumberList2.size(); ++u)
196     {
197         vecNumberList1[u] += vecNumberList2[u];
198     }
199 }
200 
201 void CDecimal::TrimVector(LONG_INT& vecNUmberList)
202 {
203     size_t size = vecNUmberList.size();
204     for (size_t u = 0; u < size ; u++)
205     {
206         if (0 == vecNUmberList[size - u - 1])
207         {
208             vecNUmberList.pop_back();
209         }
210     }
211 }
212 
213 CDecimal& CDecimal::InnerAdd(CDecimal& oRslt, CDecimal& oOther)
214 {
215     AddVector(oRslt.m_numIntiger, oOther.m_numIntiger);
216     AddVector(oRslt.m_numDecimal, oOther.m_numDecimal);
217 
218     size_t size = oRslt.m_numDecimal.size();
219     if (size > 0)
220     {
221         for (size_t u = 0; (u + 1) <  size ; u++)
222         {
223             if (oRslt.m_numDecimal[size - u - 1] >= NUM_BASE)
224             {
225                 oRslt.m_numDecimal[size - u - 2] += 1;
226                 oRslt.m_numDecimal[size - u - 1] %= NUM_BASE;
227             }
228         }
229         if (oRslt.m_numDecimal[0] >= NUM_BASE)
230         {
231             oRslt.m_numIntiger[0] += 1;
232             oRslt.m_numDecimal[0] %= NUM_BASE;
233         }
234         TrimVector(oRslt.m_numDecimal);
235     }
236 
237     size = oRslt.m_numIntiger.size();
238     for (size_t u = 0; (u + 1) < size; u++)
239     {
240         if (oRslt.m_numIntiger[u] >= NUM_BASE)
241         {
242             oRslt.m_numIntiger[u + 1] += 1;
243             oRslt.m_numIntiger[u] %= NUM_BASE;
244         }
245     }
246     if (oRslt.m_numIntiger[size - 1] >= NUM_BASE)
247     {
248         oRslt.m_numIntiger.push_back(1);
249     }
250 
251     return oRslt;
252 }
253 
254 CDecimal& CDecimal::InnerSub(CDecimal& oRslt, CDecimal& oOther)
255 {
256     size_t size = oOther.m_numDecimal.size();
257     for (size_t u = 0; u < size; u++)
258     {
259         oOther.m_numDecimal[u] = -oOther.m_numDecimal[u];
260     }
261 
262     size = oOther.m_numIntiger.size();
263     for (size_t u = 0; u < size; u++)
264     {
265         oOther.m_numIntiger[u] = -oOther.m_numIntiger[u];
266     }
267 
268     AddVector(oRslt.m_numIntiger, oOther.m_numIntiger);
269     AddVector(oRslt.m_numDecimal, oOther.m_numDecimal);
270 
271     size = oRslt.m_numDecimal.size();
272     if (size > 0)
273     {
274         for (size_t u = 0; (u + 1)< size; u++)        // size >= 2
275         {
276             if (oRslt.m_numDecimal[size - u - 1] < 0)
277             {
278                 oRslt.m_numDecimal[size - u - 2] -= 1; 
279                 oRslt.m_numDecimal[size - u - 1] += NUM_BASE;
280             }
281         }
282         if (oRslt.m_numDecimal[0] < 0)
283         {
284             oRslt.m_numDecimal[0]+= NUM_BASE;
285             oRslt.m_numIntiger[0] -= 1;
286         }
287     }
288 
289     size = oRslt.m_numIntiger.size();
290     for (size_t u = 0; (u + 1) < size; u++)        // size >= 2
291     {
292         if (oRslt.m_numDecimal[u] < 0)
293         {
294             oRslt.m_numDecimal[u + 1] -= 1; 
295             oRslt.m_numDecimal[u] += NUM_BASE;
296         }
297     }
298     //因为进入这个函数前就已经比较过大小了,就不在考虑首位为负的情况
299 
300     TrimVector(oRslt.m_numDecimal);
301     TrimVector(oRslt.m_numIntiger);
302 
303     if (oRslt.m_numIntiger.size() == 0)
304     {
305         oRslt.m_numIntiger.push_back(0);
306     }
307 
308     return oRslt;
309 }
310 
311 CDecimal CDecimal::operator + (const CDecimal &other)
312 {
313     CDecimal oRslt = (*this);
314     CDecimal oOther = other;
315 
316     if (oRslt.m_emSign == oOther.m_emSign)
317     {
318         InnerAdd(oRslt, oOther);
319         return oRslt;
320     }
321 
322     if (IsAbsBigger(oRslt, oOther))
323     {
324         InnerSub(oRslt, oOther);
325         return oRslt;
326     }
327     else
328     {
329         InnerSub(oOther, oRslt);
330          return oOther;
331     }
332 }
333 
334 CDecimal CDecimal::operator - (const CDecimal &other)
335 {
336     CDecimal oRslt = (*this);
337     CDecimal oOther = other;
338 
339     oOther.m_emSign = (SIGN_ENUM)(- oOther.m_emSign);
340     return oRslt + oOther;
341 }
342 
343 
344 LONG_INT CDecimal::GetVectorByObj(const CDecimal& oOther)
345 {
346     LONG_INT vecNumber;
347 
348     LONG_INT::const_reverse_iterator reiter = oOther.m_numDecimal.rbegin();
349    for (; reiter != oOther.m_numDecimal.rend(); reiter++)
350    {
351        vecNumber.push_back(*reiter);
352    }
353 
354    LONG_INT::const_iterator iter = oOther.m_numIntiger.begin();
355    for (; iter != oOther.m_numIntiger.end(); iter++)
356    {
357         vecNumber.push_back(*iter);
358    }
359 
360    return vecNumber;
361 }
362 
363 void CDecimal::GetObjByVector(CDecimal& oRlst, const LONG_INT& vecRlst, size_t uDecaimalCount)
364 {
365     oRlst.m_numIntiger.clear();
366     oRlst.m_numDecimal.clear();
367     oRlst.m_numDecimal.resize(uDecaimalCount);
368 
369     size_t uPointPos =  uDecaimalCount - 1;
370     for (size_t u = 0; u < uDecaimalCount; u++)
371     {
372         oRlst.m_numDecimal.push_back(vecRlst[uPointPos - u]);
373     }
374     for (size_t u = uPointPos; u < vecRlst.size(); u++)
375     {
376         oRlst.m_numIntiger.push_back(vecRlst[u]);
377     }
378 }
379 
380 void CDecimal::InnerMuti(LONG_INT& vecRslt, const LONG_INT& vecThis, const LONG_INT& vecOther)
381 {
382     for (size_t uOther = 0; uOther < vecOther.size(); uOther++)
383     {
384         for (size_t uThis = 0; uThis < vecThis.size(); uThis++)
385         {
386             vecRslt[uOther + uThis] += vecThis[uThis] * vecOther[uOther];
387         }
388         for (size_t uRlst = 0; (uRlst + 1) < vecRslt.size(); uRlst++)
389         {
390             vecRslt[uRlst + 1] += vecRslt[uRlst] / NUM_BASE;
391             vecRslt[uRlst] %= NUM_BASE;
392         }
393     }
394 }
395 
396 CDecimal CDecimal::operator * (const CDecimal &other)
397 {
398     CDecimal oRslt;
399 
400     size_t uDecimalCount = this->m_numDecimal.size() + other.m_numDecimal.size(); // 小数部分的位数
401     size_t uRlstSize = (this->m_numIntiger.size() + this->m_numDecimal.size()) * (other.m_numIntiger.size() + other.m_numDecimal.size()) + 1;
402 
403     LONG_INT vecRlst(uRlstSize);
404     LONG_INT vecThis = GetVectorByObj(*this);
405     LONG_INT vecOther = GetVectorByObj(other);
406 
407     InnerMuti(vecRlst, vecThis, vecOther);
408 
409     GetObjByVector(oRslt, vecRlst, uDecimalCount);
410 
411     TrimVector(oRslt.m_numDecimal);
412     TrimVector(oRslt.m_numIntiger);
413 
414     oRslt.m_emSign =  (SIGN_ENUM)(this->m_emSign * other.m_emSign);
415 
416     return oRslt;
417 }
418 
419 
420 
421 CDecimal CDecimal::operator / (const CDecimal &other)
422 {
423     CDecimal oRslt;
424 
425     // TODO:
426 
427     return oRslt;
428 }
429 
430 bool CDecimal::operator == (const CDecimal &other)
431 {
432     if (this->m_emSign != other.m_emSign
433         || this->m_numDecimal.size() != other.m_numDecimal.size()
434         || this->m_numIntiger.size() != other.m_numDecimal.size())
435     {
436         return false;
437     }
438 
439     for (size_t u = 0; u < this->m_numIntiger.size(); u++)
440     {
441         if (this->m_numIntiger[u] != other.m_numIntiger[u])
442         {
443             return false;
444         }
445     }
446 
447     for (size_t u = 0; u < this->m_numDecimal.size(); u++)
448     {
449         if (this->m_numDecimal[u] != other.m_numDecimal[u])
450         {
451             return false;
452         }
453     }
454 
455     return true;
456 }
457 
458 bool CDecimal::IsAbsBigger(const CDecimal& oNumber1, const CDecimal& oNumber2)
459 {
460     if (oNumber1.m_numIntiger.size()  != oNumber2.m_numIntiger.size())
461     {
462         return oNumber1.m_numIntiger.size() > oNumber2.m_numIntiger.size();
463     }
464 
465     for (size_t u = oNumber1.m_numIntiger.size() - 1; u < oNumber2.m_numIntiger.size(); --u)
466     {
467         if (oNumber1.m_numIntiger[u] == oNumber2.m_numIntiger[u])
468         {
469             continue;
470         }
471 
472         if (oNumber1.m_numIntiger[u] > oNumber2.m_numIntiger[u])
473         {
474             return true;
475         }
476 
477         if (oNumber1.m_numIntiger[u] < oNumber2.m_numIntiger[u])
478         {
479             return false;
480         }
481     }
482 
483     size_t uDecimalLenth = Min(oNumber1.m_numDecimal.size(), oNumber2.m_numDecimal.size());
484     for (size_t u = 0; u < uDecimalLenth; ++u)
485     {
486         if (oNumber1.m_numDecimal[u] == oNumber2.m_numDecimal[u])
487         {
488             continue;
489         }
490 
491         if (oNumber1.m_numDecimal[u] > oNumber2.m_numDecimal[u])
492         {
493             return true;
494         }
495 
496         if (oNumber1.m_numDecimal[u] < oNumber2.m_numDecimal[u])
497         {
498             return false;
499         }
500     }
501 
502     return oNumber1.m_numDecimal.size() > oNumber2.m_numDecimal.size();
503 }
504 
505 bool CDecimal::operator > (const CDecimal &other)
506 {
507     if ((*this) == other)
508     {
509         return false;
510     }
511 
512     if ((SIGN_POSTIVE == this->m_emSign) && (SIGN_NAGETIVE == other.m_emSign))
513     {
514         return true;
515     }
516 
517     if ((SIGN_NAGETIVE == this->m_emSign) && (SIGN_POSTIVE == other.m_emSign))
518     {
519         return false;
520     }
521 
522     if (SIGN_POSTIVE == this->m_emSign)
523     {
524         return IsAbsBigger((*this), other);
525     }
526 
527     return !IsAbsBigger((*this), other);
528 }
529 
530 bool CDecimal::operator < (const CDecimal &other)
531 {
532     if ((*this) > other || (*this) == other)
533     {
534         return false;
535     }
536     return true;
537 }
538 
539 /************************************************************************/
540 /*           其他函数                                                                                                                               */
541 /************************************************************************/
542 size_t CDecimal::IntigerLenth()
543 {
544     return m_numIntiger.size();
545 }
546 
547 size_t CDecimal::DecamalLenth()
548 {
549     return m_numDecimal.size();
550 }
551 
552 SIGN_ENUM CDecimal::Sign()
553 {
554     return m_emSign;
555 }
556 
557 bool CDecimal::IsPostive()
558 {
559     return m_emSign == SIGN_POSTIVE;
560 }
561 
562 string CDecimal::ToString()
563 {
564     return ToString(m_numDecimal.size());
565 }
566 
567 string CDecimal::ToString(size_t uDecimalLenth)
568 {
569     string strNumber;
570     stringstream ssNumber("");
571 
572     if(SIGN_NAGETIVE == m_emSign)
573     {
574         ssNumber << '-';
575     }
576 
577     for(size_t u = m_numIntiger.size() - 1; u >= 0 && u < m_numIntiger.size(); --u)
578     {
579         ssNumber << (int)m_numIntiger[u];
580     }
581 
582     if(uDecimalLenth > 0 || m_numDecimal.size() > 0)
583     {
584         ssNumber << '.';
585     }
586 
587     if(uDecimalLenth < m_numDecimal.size())
588     {
589         for(size_t u = 0; u < uDecimalLenth; ++u)
590         {
591             ssNumber << (int)m_numDecimal[u];
592         }
593         return ssNumber.str();
594     }
595 
596     for(size_t u = 0; u < m_numDecimal.size(); ++u)
597     {
598         ssNumber << (int)m_numDecimal[u];
599     }
600     for(size_t u = m_numDecimal.size(); u < uDecimalLenth; ++u)
601     {
602         ssNumber << (int)0;
603     }
604 
605     return ssNumber.str();
606 }
607 
608 /************************************************************************/
609 /*            静态函数区                                                                                                                          */
610 /************************************************************************/
611 
612  CDecimal& CDecimal::Ceil(CDecimal& dDecimal)
613 {
614     if (dDecimal.m_numDecimal.size() > 0)
615     {
616         dDecimal = dDecimal + 1LL;
617     }
618     dDecimal.m_numDecimal.clear();
619     return dDecimal;
620 }
621  CDecimal& CDecimal::Floor(CDecimal& dDecimal)
622  {
623      if (dDecimal.m_numDecimal.size() > 0)
624      {
625          dDecimal = dDecimal - 1LL;
626      }
627      dDecimal.m_numDecimal.clear();
628      return dDecimal;
629  }
630   
631  CDecimal& CDecimal::Round(CDecimal& dDecimal)
632  {
633      dDecimal = dDecimal + CDecimal("0.5");
634      return Floor(dDecimal);
635  }
05-11 09:33