在C#和Java中都有存在decimal类似的十进制数字,C++中尚未发现,春节假期忙里抽闲写了一个玩玩,时间紧迫没有测试,只能保证编译通过。抛砖引玉,欢迎大家多提建议
当前缺陷:
1. 除法功能没有实现
2. 没有测试
3. 代码比较乱没有重构,部分命名不规范
4. 算法效率比较低
老规矩直接上代码:
VS 2010 工程
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 }