高精整数数、纯小数类,支持加减法

之前加减法的强化版,里面自带了高精整数类,高精小数类,都分别定义了加减法

 

重点是技巧性可能不高,存档用吧

 

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

posted @ 2010-10-23 00:45  幻魇  阅读(392)  评论(0编辑  收藏  举报