高精度整数模板(转)

来源:互联网 发布:x77大陆永久域名 编辑:程序博客网 时间:2024/06/06 08:33
  1. * *
  2. * 高精度模板 *
  3. * *
  4. * 功能:超长符号整数(HarInt)+,-,*,/,%,+=,-=,*=,/=,%= 等运算 *
  5. *支持大小比较<,>,==,!=,<=,>=*
  6. * 多种操作运算符的重载 *
  7. *说明:HarInt采用一个有上界的数组及一个bool变量表示 *
  8. * 数组的第一位表示数的位数,bool变量表示数的符号 *
  9. * 特殊数字0的符号强制为正,即bool值为true*
  10. * 采用了9位整形数为计算单元,提高运算效率 *
  11. * 加法,减法,乘法采用了比较简单的模拟运算,效率一般*
  12. * 除法采用了二分试商,取最高二位取商的最大值及最小值,然后二分试商*
  13. * *
  14. *************************** All RightsReserved ********************************/
  15. #include<iostream>
  16. #define MAXLEN450//数组长度上限,可以根据需求自行设置
  17. #define BASE_DIGIT9//运算的进制,9代表以10^9计算
  18. #define BASE1000000000//10^9进制
  19. #define PRINTCHAR ("d")//专长整数输出定义的字符串
  20. #define IsDigit(c)(('0'<=(c))&&((c)<='9'))//判断字符c是否为数字
  21. using namespace std;
  22. charinstr[MAXLEN*BASE_DIGIT+1];
  23. shortCMP(const int *a,const int*b){//比较数组大整数,也就是大整数的绝对值
  24. if(a[0]<b[0])//数位少的小
  25. return -1;
  26. if(a[0]>b[0])//数位多的大
  27. return 1;
  28. for(inti=a[0];i>0;i--)
  29. {
  30. if(a[i]<b[i])//高位小的小
  31. return -1;
  32. if(a[i]>b[i])//高位大的数大
  33. return 1;
  34. }
  35. return 0;
  36. }
  37. void ADD(const int*a,const int *b,int *c){//数组表示的大整数加法
  38. memset(c,0,sizeof(int)*MAXLEN);
  39. intla=a[0],lb=b[0],d=0;
  40. c[0]=(la>lb?la:lb)+1;
  41. for(inti=1;i<=c[0];i++)
  42. {
  43. c[i]= a[i]+b[i]+d;
  44. d=0;
  45. if(c[i]>=BASE)
  46. {//需要进位
  47. d=1;
  48. c[i]-=BASE;
  49. }
  50. }
  51. while(c[0]>1&&c[c[0]]==0)//消去前导零
  52. c[0]--;
  53. }
  54. voidSUB(const int *a,const int*b,int*c){//减法
  55. memset(c,0,sizeof(int)*MAXLEN);
  56. c[0]=a[0];
  57. int d=0;
  58. for(inti=1;i<=a[0];i++)
  59. {
  60. c[i]=a[i]-b[i]-d;
  61. d=0;
  62. if(c[i]<0)
  63. {//需要借位
  64. c[i]+=BASE;
  65. d++;
  66. }
  67. }
  68. while(c[0]>1&&c[c[0]]==0)
  69. c[0]--;//消去前导零
  70. return;
  71. }
  72. voidMUL(const int *a,const int*b,int*c){//乘法
  73. memset(c,0,sizeof(int)*MAXLEN);
  74. __int64t=0;
  75. int l =a[0]+b[0]+1;
  76. c[0]=l;
  77. for(inti=1;i<=a[0];i++)
  78. for(intj=1;j<=b[0];j++)
  79. {
  80. t=(__int64)c[i+j-1]+(__int64)a[i]*(__int64)b[j];
  81. c[i+j-1]=t�SE;
  82. c[i+j] += t/BASE;//存储进位
  83. }
  84. while(c[0]>1&&c[c[0]]==0)
  85. c[0]--;//消去前导零
  86. }
  87. voidMUL(const int *a,int b,int *c){//高精乘单精
  88. memset(c,0,sizeof(int)*MAXLEN);
  89. int l = a[0] +1 ;
  90. __int64 t=0;
  91. for(inti=1;i<=l;i++)
  92. {
  93. t = (__int64)a[i]*b + (__int64)c[i];
  94. c[i+1] = t/BASE;
  95. c[i] = (t�SE);
  96. }
  97. while(c[l]==0&&l>1)l--;
  98. c[0]=l;
  99. }
  100. void DIV(const int*a,const int *b,int *c,int *d){//除法
  101. memset(c,0,sizeof(int)*MAXLEN);memset(d,0,sizeof(int)*MAXLEN);
  102. int *t1 =new int[MAXLEN],*t2 = new int[MAXLEN];
  103. intla=a[0],lb=b[0],ld=0,min=0,max=0,mid=0,l = la;
  104. doubletdmin=0,tdmax=0,tbmin=b[lb],tbmax=tbmin+1.0;
  105. if(lb>1)
  106. {//取两个高位的值,用作试商
  107. tbmin = tbmin*(double)BASE + (double)b[lb-1];
  108. tbmax = tbmin+1.0;
  109. }
  110. for(inti=l;i>0;i--)
  111. {
  112. for(intj=d[0];j>=1;j--)d[j+1]=d[j];d[1]=a[i];
  113. if(d[d[0]+1]!=0)d[0]++;
  114. if(CMP(d,b)<0)
  115. continue;
  116. ld = d[0];
  117. tdmin = d[ld];
  118. int j = 1;
  119. while(tdmin<tbmin)
  120. {
  121. tdmin = tdmin*BASE + d[ld-j];
  122. j++;
  123. }
  124. tdmax = tdmin+1.0;
  125. max =(int)(tdmax/tbmin)+1;min=(int)(tdmin/tbmax)-1;
  126. while(true)
  127. {//二分试商
  128. mid = (min+max)/2;
  129. MUL(b,mid,t1);
  130. if(CMP(d,t1)<0){max =mid-1;continue;}//试商偏高,改变max值
  131. SUB(d,t1,t2);
  132. if(CMP(t2,b)>=0){min =mid+1;continue;}//试商偏低,改变min值
  133. break;//试商成功,此mid值为该位的商值
  134. }
  135. c[i]=mid;
  136. memcpy(d,t2,sizeof(int)*MAXLEN);//t2为余值,赋给d
  137. }
  138. delete[]t1;delete[]t2;
  139. while(c[l]==0&&l>1)l--;
  140. c[0]=l;//消去前导零
  141. }
  142. class HarInt{
  143. private:
  144. intnumb[MAXLEN];//具体数字,第0位表示数字长度,第一位及以后分别表示数字的高位至低位
  145. boolflag;
  146. public:
  147. HarInt(){}
  148. ~HarInt(){}
  149. boolParse(const char *s){
  150. clear();intl=strlen(s),i=0,nl=1;flag = true;//默认为非负数
  151. if(s[0]=='-'){i++;flag = false;}//为负数,数值从第2位开始
  152. for(intj=l-1;j>=i;j-=BASE_DIGIT)
  153. {//从高位至低位一位一位转
  154. int n=0,ten=1;
  155. for(intk=0;(k<BASE_DIGIT&&j-k>=i);k++)
  156. {
  157. if(!IsDigit(s[j-k])){clear();returnfalse;}//含非数字字符,赋值失败
  158. n+=(s[j-k]-'0')*ten;ten*=10;
  159. }
  160. numb[nl++]=n;//从第一位开始给数组numb赋值,第0位预留为数字长
  161. }
  162. nl--;while(numb[nl]==0&&nl>1)nl--;//消去前导零
  163. numb[0]=nl;return true;//赋值成功
  164. }
  165. voidclear(){memset(numb,0,sizeof(int)*MAXLEN);}
  166. voidParse(const HarInthi){
  167. memcpy(numb,hi.numb,sizeof(int)*MAXLEN);
  168. flag = hi.flag;
  169. }
  170. voidvalue(const int a){
  171. intt=a;
  172. flag=true;if(t<0){flag=false;t*=-1;}
  173. numb[0]=1;numb[1]=t;
  174. }
  175. intoperator[](inti){returnnumb[i];}
  176. boolFlag(){returnflag;}
  177. boolisZero(){return(numb[0]==1&&numb[1]==0);}
  178. intGet(){if(scanf("%s",instr)==EOF)return EOF;return Parse(instr);}
  179. voidprint(chars){
  180. if(!flag)putchar('-');
  181. printf("%d",numb[numb[0]]);
  182. for(inti=numb[0]-1;i>=1;i--)
  183. printf(PRINTCHAR,numb[i]);
  184. putchar(s);
  185. }
  186. friend shortHarIntCmp(HarInt,HarInt);//友元比较函数
  187. friend voidDIV(HarInt,HarInt,HarInt&,HarInt&);//友元除法函数
  188. HarInt& operator+=(const HarInt&a){//重载+=运算符,实现大整数的+=运算
  189. int *n= new int[MAXLEN];
  190. memcpy(n,numb,sizeof(int)*MAXLEN);
  191. if(flag==a.flag)//同号,绝对值直接相加,符号不变
  192. ADD(n,a.numb,numb);
  193. else{//异号则绝对值大的减绝对值小的,符号与绝对值大的相同
  194. int c =CMP(n,a.numb);//比较两数的绝对值
  195. if(c==0){numb[0]=1;numb[1]=0;flag=true;}//|a|==|b|&&a*b<0则a-b=0;
  196. else if(c<0){SUB(a.numb,n,numb);flag=a.flag;}//|a|<|b|
  197. elseSUB(n,a.numb,numb);
  198. }
  199. delete[]n;n=NULL;
  200. return *this;
  201. }
  202. HarInt& operator-=(const HarInt&a){//重载-=运算符,实现大整数的-=运算
  203. int *n= new int[MAXLEN];
  204. memcpy(n,numb,sizeof(int)*MAXLEN);
  205. if(flag!=a.flag)//异号,绝对值直接相加,符号不变
  206. ADD(n,a.numb,numb);
  207. else{//同号,绝对值大减小,符号由两数的大小确定
  208. int c =CMP(n,a.numb);
  209. if(c==0){numb[0]=1;numb[1]=0;flag=true;}//0
  210. else if(c<0){SUB(a.numb,n,numb);flag=!flag;}//a<b符号取反
  211. elseSUB(n,a.numb,numb);//a>b符号不变
  212. }
  213. delete[]n;n=NULL;
  214. return *this;
  215. }
  216. HarInt& operator*=(const HarInt&a){//重载*=运算符,实现大整数的*=运算
  217. int *n= new int[MAXLEN];
  218. memcpy(n,numb,sizeof(int)*MAXLEN);
  219. MUL(n,a.numb,numb);//绝对值相乘
  220. flag = (flag==a.flag);//同号取正,异号取负
  221. delete[]n;n=NULL;
  222. return *this;
  223. }
  224. HarInt& operator/=(const HarInt&a){//重载/=运算符,实现大整数的/=运算
  225. int *n1= new int[MAXLEN],*n2 = new int[MAXLEN];
  226. memcpy(n1,numb,sizeof(int)*MAXLEN);
  227. DIV(n1,a.numb,numb,n2);//绝对值相除
  228. delete[]n1;delete[]n2;
  229. flag = (flag==a.flag);//同号取正,异号取负
  230. return *this;
  231. }
  232. HarInt& operator%=(const HarInt&a){//重载%=运算符,实现大整数的%=运算
  233. int *n1= new int[MAXLEN],*n2 = new int[MAXLEN];
  234. memcpy(n1,numb,sizeof(int)*MAXLEN);
  235. DIV(n1,a.numb,n2,numb);
  236. delete[]n1;delete[]n2;
  237. flag = (flag==a.flag);
  238. return *this;
  239. }
  240. };
  241. void DIV(HarInta,HarInt b,HarInt& c,HarInt&d){//除法,一次运算同时取得商与余数
  242. c.flag= (a.flag==b.flag);d.flag=c.flag;
  243. DIV(a.numb,b.numb,c.numb,d.numb);
  244. return ;
  245. }
  246. short HarIntCmp(HarInta,HarInt b){
  247. if(a.Flag()>b.Flag())//正数恒大于负数
  248. return 1;
  249. if(a.Flag()<b.Flag())//负数恒小于正数
  250. return -1;
  251. if(a[0]<b[0])//数位少的数值小,根据符号判断大小
  252. return((!a.Flag())?1:-1);
  253. if(a[0]>b[0])
  254. return(a.Flag()?1:-1);
  255. for(inti=a[0];i>=1;i--)
  256. {
  257. if(a[i]<b[i])
  258. return((!a.Flag())?1:-1);
  259. if(a[i]>b[i])
  260. return(a.Flag()?1:-1);
  261. }
  262. return 0;
  263. }
  264. booloperator<(HarInt a,HarIntb){return(HarIntCmp(a,b)<0);}
  265. booloperator>(HarInt a,HarIntb){return(HarIntCmp(a,b)>0);}
  266. booloperator==(HarInt a,HarInt b){return (HarIntCmp(a,b)==0);}
  267. bool operator!=(HarInta,HarInt b){return(HarIntCmp(a,b)!=0);}
  268. booloperator<=(HarInt a,HarIntb){return(HarIntCmp(a,b)<=0);}
  269. booloperator>=(HarInt a,HarIntb){return(HarIntCmp(a,b)>=0);}
  270. HarInt operator+(const HarInt&a,constHarInt& b){HarIntc=a;c+=b;returnc;}
  271. HarInt operator+(const HarInt&a,const int b){HarIntc;c.value(b);c+=a;returnc;}
  272. HarInt operator-(const HarInt&a,constHarInt& b){HarIntc=a;c-=b;returnc;}
  273. HarInt operator-(const HarInt&a,const int b){HarIntc;c.value(b);return(a-c);}
  274. HarInt operator*(const HarInt&a,constHarInt& b){HarIntc=a;c*=b;returnc;}
  275. HarInt operator*(const HarInt&a,const int b){HarIntc;c.value(b);c*=a;returnc;}
  276. HarInt operator/(const HarInt&a,constHarInt& b){HarIntc=a;c/=b;returnc;}
  277. HarInt operator/(const HarInt&a,const int b){HarIntc;c.value(b);return(a/c);}
  278. HarInt operator%(const HarInt&a,constHarInt& b){HarIntc=a;c%=b;returnc;}
  279. HarInt operator%(const HarInt&a,const int b){HarIntc;c.value(b);return(a%c);}
原创粉丝点击