在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 }