高精整数数、纯小数类,支持加减法
之前加减法的强化版,里面自带了高精整数类,高精小数类,都分别定义了加减法
重点是技巧性可能不高,存档用吧
main.cpp:
#include<iostream> #include"num.h" #include<conio.h> int main() { num k1,k2; std::cout<<"欢迎使用高精度加减法器!!!"<<std::endl; int what; for(;;) { std::cout<<"输入1键执行加法,输入2键执行减法,0键退出。"<<std::endl; what=_getch(); if(!((what=='1')||(what=='2')||(what=='0'))) continue; if(what=='0') break; std::cout<<"请输入第一个数"<<std::endl; std::cin>>k1; std::cout<<"请输入第二个数"<<std::endl; std::cin>>k2; std::cout<<"结果是:"<<std::endl; if(what=='1') std::cout<<k1+k2<<std::endl; if(what=='2') std::cout<<k1-k2<<std::endl; } return 0; }
num.h:
#pragma once #ifndef NUM_H #define NUM_H #include<iostream> #include"exnum.h" #include"exrenum.h" class num { friend num operator+(const num&,const num&); friend num operator-(const num&,const num&); friend std::ostream& operator<<(std::ostream&,const num&); friend std::istream& operator>>(std::istream& is,num& in); private: exrenum ex; exnum n; public: void postion(); }; inline std::ostream& operator<<(std::ostream& os,const num& in) { os<<in.n<<'.'<<in.ex; return os; } #endif
exrenum.h:
#pragma once #ifndef EXRENUM_H #define EXRENUM_H #include "exnum.h" #include <iostream> class exrenum { friend class num; friend std::ostream& operator<<(std::ostream&,const exrenum&); friend std::istream& operator>>(std::istream& is,exrenum& ienx); friend exrenum operator+(const exrenum& iex1t,const exrenum& iex2t); friend exrenum operator-(const exrenum& iex1,const exrenum& iex2); friend void in_row(exrenum&,exrenum&); friend void astyle(exrenum& iex); public: exrenum operator-()const; exrenum():renum(),h_level(0){}; private: long h_level; exnum renum; void make_in_low(); }; #endif
exnum.h:
#pragma once #ifndef EXNUM_H #define EXNUM_H #include<list> #include<iostream> #include<sstream> class exnum { friend class num; typedef long num_type; typedef std::list<num_type> num_list; friend class exrenum; friend exnum operator-(const exnum&,const exnum&); friend exnum operator+(const exnum& e1,const exnum& e2); friend bool operator<(const exnum& e1,const exnum& e2); friend std::ostream& operator<<(std::ostream&,const exnum&); friend std::istream& operator>>(std::istream&,exnum&); friend exnum real_plus(const exnum& e1,const exnum& e2); friend exnum real_mui(const exnum& e1,const exnum& e2); friend std::istream& operator>>(std::istream& is,exrenum& ienx); friend std::ostream& operator<<(std::ostream&,const exrenum&); friend std::string re_format(long il,bool head,bool tail); friend exrenum operator+(const exrenum& iex1t,const exrenum& iex2t); friend exrenum operator-(const exrenum& iex1,const exrenum& iex2); friend void in_row(exrenum& iex1,exrenum& iex2); friend void astyle(exrenum& iex); friend bool smaller(const exnum& e1,const exnum& e2); public: void push_back(long il) { num.push_back(il); } exnum():negative(false) { num.push_back(0); } exnum(const exnum& ien):num(ien.num),negative(ien.negative){} exnum(const long il) { if(il<0) { negative=true; num.clear(); num.push_back(-il); } else { negative=false; num.clear(); num.push_back(il); } } inline exnum operator-() const; bool if_negative() const { return negative; } inline std::string format(num_type il, std::string::size_type numw, bool if_align=false, std::string::size_type total=9)const; private: num_list num; bool negative; }; std::string exnum::format(exnum::num_type il, std::string::size_type numw, bool if_align, std::string::size_type total) const { if (total%numw!=0) { total=9; numw=3; } std::ostringstream iss; iss<<il; std::string tmp_str1(iss.str()),tmp_str2; tmp_str2.reserve(total+total/3); std::string::size_type hlen,need_to_output; std::string::iterator iter=tmp_str1.begin(); hlen=tmp_str1.size() %numw; need_to_output=9-tmp_str1.size(); if(if_align) while(need_to_output>numw-hlen) { tmp_str2.append(",000"); if(need_to_output>numw-hlen+3) break; need_to_output-=3; } if (if_align) { tmp_str2.push_back(','); if (hlen!=0) tmp_str2.append(std::string(numw-hlen,'0')); } if (hlen==0) hlen=numw; tmp_str2.append(std::string(iter,iter+hlen)); iter+=hlen; for (; (iter!=tmp_str1.end())&&(iter+numw<=tmp_str1.end()); iter+=numw) { tmp_str2.push_back(','); tmp_str2.append(std::string(iter,iter+numw)); } return tmp_str2; } exnum exnum::operator-() const { exnum tmp_e(*this); tmp_e.negative=(negative?false:true); return tmp_e; } #endif
exnum.cpp:
#include "exnum.h" #include <string> #include <sstream> #define NUM_LENTH 3 #define BASE_NUMBER 1000000000 bool operator<(const exnum& e1,const exnum& e2) { if (e1.num.size()!=e2.num.size()) return e1.num.size()<e2.num.size(); exnum::num_list::const_iterator iter1(e1.num.begin()),iter2(e2.num.begin()); do { if ((*iter1)!=(*iter2)) return (*iter1)<(*iter2); } while (iter1!=e1.num.end()); return false; } std::istream& operator>>(std::istream& is,exnum& ien) { ien.num.clear(); if (is.peek()=='-') { ien.negative=true; is.ignore(); } std::string getin; std::getline(is,getin); exnum::num_type tmp_long; std::string::iterator i; i=getin.begin(); std::istringstream iss(std::string(i,i+(getin.size()%9))); if (getin.size()%9!=0) { iss>>tmp_long; ien.num.push_back(tmp_long); } i+=getin.size()%9; iss.clear(); for (; 9<getin.end()-i; i+=9) { iss.str(std::string(i,i+9)); iss>>tmp_long; ien.num.push_back(tmp_long); iss.clear(); } if (i!=getin.end()) { iss.str(std::string(i,getin.end())); iss>>tmp_long; ien.num.push_back(tmp_long); } return is; } std::ostream& operator<<(std::ostream& os,const exnum& ien) { if (ien.num.empty()) return os; if (ien.negative) os<<'-'; exnum::num_list::const_iterator i=ien.num.begin(); os<<ien.format(*i,NUM_LENTH); for (++i; i!=ien.num.end(); ++i) { os<<ien.format(*i,NUM_LENTH,true); } return os; } exnum real_plus(const exnum& e1,const exnum& e2); exnum real_mui(const exnum& e1,const exnum& e2); exnum operator+(const exnum& e1,const exnum& e2) { if ((!e1.negative)&&(!e2.negative)) return real_plus(e1,e2); if ((e1.negative)&&(e2.negative)) return -real_plus(e1,e2); if (e1.negative) return real_mui(e2,e1); else return real_mui(e1,e2); } exnum real_plus(const exnum& e1,const exnum& e2) { exnum tmp_e; tmp_e.num.clear(); const exnum *e_small,*e_big; if (e1.num.size()>e2.num.size()) { e_small=&e2; e_big=&e1; } else { e_small=&e1; e_big=&e2; } exnum::num_list::const_reverse_iterator end1(e_small->num.rend()),end2(e_big->num.rend()); exnum::num_list::const_reverse_iterator i(e_big->num.rbegin()),j(e_small->num.rbegin()); exnum::num_type hlevel(0); for (; j!=end1;) { tmp_e.num.push_front(*i + *j+hlevel); if (*i+*j>BASE_NUMBER) { *tmp_e.num.begin()-=BASE_NUMBER; hlevel=1; } else hlevel=0; ++i; ++j; } if (hlevel) { if (i==end2) tmp_e.num.push_front(1); else tmp_e.num.push_front(1+*i++); } for (; i!=end2;) { tmp_e.num.push_front(*i++); } return tmp_e; } exnum operator-(const exnum& e1,const exnum& e2) { return e1+(-e2); } exnum real_mui(const exnum& e1,const exnum& e2) { if (e1<e2) return -real_mui(e2,e1); exnum tmp_e(e1); exnum::num_list::reverse_iterator iter1(tmp_e.num.rbegin()); exnum::num_list::const_reverse_iterator iter2(e2.num.rbegin()); for (; iter2!=e2.num.rend(); ++iter2) { (*iter1)-=(*iter2); if(*iter1<0) { (*iter1)+=BASE_NUMBER; (*++iter1)-=1; } else ++iter1; } tmp_e.negative=false; return tmp_e; }
exrenum.cpp:
#include "exrenum.h" #include "exnum.h" #include<string> #include<sstream> std::istream& operator>>(std::istream& is,exrenum& ienx) { if (is.peek()=='.') is.ignore(); std::string tmp_str; std::getline(is,tmp_str); ienx.renum.num.clear(); long tmp_long; std::string::size_type hlen(9-(tmp_str.size()%9)); if (hlen==9) hlen=0; tmp_str.append(hlen,'0'); std::string::iterator i(tmp_str.begin()); for (; i!=tmp_str.end(); i+=9) { std::istringstream(std::string(i,i+9))>>tmp_long; ienx.renum.push_back(tmp_long); } if (ienx.renum.num.empty()) { ienx.renum.num.push_back(0); return is; } if (*ienx.renum.num.begin()==0) return is; exnum::num_list::reverse_iterator ri=ienx.renum.num.rbegin(); for (; (*ri==0)&&(ri!=ienx.renum.num.rend()); ++ri) ienx.renum.num.pop_back(); return is; } std::string re_format(long il,bool head,bool tail) { std::string out_str(exnum().format(il,3,true)); std::string::size_type i=out_str.size()-1; if (tail) for (; i!=-1&&(out_str[i]=='0'||out_str[i]==','); --i); ++i; if (tail) out_str.erase(i,out_str.size()); if (out_str.empty()) return "0"; if (head) return out_str.substr(1,i); else return out_str.substr(0,i); } std::ostream& operator<<(std::ostream& os,const exrenum& inex) { if (inex.renum.num.size()==1) { os<<re_format(*(inex.renum.num.begin()),true,true); return os; } exnum::num_list::const_iterator i=inex.renum.num.begin(); os<<re_format(*i++,true,false); for (; i!=inex.renum.num.end(); ++i) { os<<re_format(*i,false,false); } --i; os<<re_format(*i,false,true); return os; } void in_row(exrenum& iex1,exrenum& iex2) { if (iex1.renum.num.size()==iex2.renum.num.size()) return; exrenum *small,*big; if (iex1.renum.num.size()<iex2.renum.num.size()) { small=&iex1; big=&iex2; } else { small=&iex2; big=&iex1; } do { small->renum.num.push_back(0); } while (small->renum.num.size()<big->renum.num.size()); } void astyle(exrenum& iex) { iex.h_level-=1; exrenum tmp_e; tmp_e.renum.num.resize(iex.renum.num.size(),0); *tmp_e.renum.num.begin()=1000000000; iex.renum=tmp_e.renum+iex.renum; } exrenum operator+(const exrenum& iex1t,const exrenum& iex2t) { exrenum iex1(iex1t),iex2(iex2t); in_row(iex1,iex2); exnum::num_list::size_type l(iex1.renum.num.size()); exrenum out_e; out_e.renum=iex1.renum+iex2.renum; if (out_e.renum.num.size()>l) { out_e.h_level=*out_e.renum.num.begin(); out_e.renum.num.pop_front(); } if (iex1.renum.negative) out_e.h_level-=iex1.h_level; else out_e.h_level+=iex1.h_level; if (iex2.renum.negative) out_e.h_level-=iex2.h_level; else out_e.h_level+=iex2.h_level; if (out_e.renum.negative) astyle(out_e); return out_e; } exrenum exrenum::operator-() const { exrenum tmp_e(*this); tmp_e.h_level=-tmp_e.h_level; tmp_e.renum.negative=true; astyle(tmp_e); return tmp_e; } exrenum operator-(const exrenum& iex1,const exrenum& iex2) { return iex1+(-iex2); }
num.cpp:
#include"num.h" #include<string> void num::postion() { this->n=this->n+exnum(ex.h_level); if(n<exnum(0)) { n=n-exnum(1); ex.renum.negative=true; ex=-ex; } ex.h_level=0; } num operator+(const num& n1,const num& n2) { num tmp_n; tmp_n.n=n1.n+n2.n; tmp_n.ex=n1.ex+n2.ex; tmp_n.postion(); return tmp_n; } num operator-(const num& n1,const num& n2) { num tmp_n; tmp_n.n=n1.n-n2.n; tmp_n.ex=n1.ex-n2.ex; tmp_n.postion(); return tmp_n; } std::istream& operator>>(std::istream& is,num& in) { std::string tmp_s; std::getline(is,tmp_s); std::istringstream iss; std::string::size_type i(0),len(tmp_s.size()); for(;(i!=tmp_s.size())&&(tmp_s[i]!='.');++i); if(i!=0) { iss.str(tmp_s.substr(0,i)); iss>>in.n; iss.clear(); } if(i!=len) { iss.str(tmp_s.substr(i,len)); iss>>in.ex; } return is; }