高精度整数模板(转)

  1. * *
  2. * 高精度模板 *
  3. * *
  4. * 功能:超长符号整数(HarInt) +,-,*,/,%,+=,-=,*=,/=,%= 等运算 *
  5. * 支持大小比较<,>,==,!=,<=,>= *
  6. * 多种操作运算符的重载 *
  7. * 说明:HarInt采用一个有上界的数组及一个bool变量表示 *
  8. * 数组的第一位表示数的位数,bool变量表示数的符号 *
  9. * 特殊数字0的符号强制为正,即bool值为true *
  10. * 采用了9位整形数为计算单元,提高运算效率 *
  11. * 加法,减法,乘法采用了比较简单的模拟运算,效率一般 *
  12. * 除法采用了二分试商,取最高二位取商的最大值及最小值,然后二分试商 *
  13. * *
  14. *************************** All Rights Reserved ********************************/
  15. #include<iostream>
  16. #define MAXLEN 450//数组长度上限,可以根据需求自行设置
  17. #define BASE_DIGIT 9//运算的进制,9代表以10^9计算
  18. #define BASE 1000000000//10^9进制
  19. #define PRINTCHAR (" d")//专长整数输出定义的字符串
  20. #define IsDigit(c) (('0'<=(c))&&((c)<='9'))//判断字符c是否为数字
  21. using namespace std;
  22. char instr[MAXLEN*BASE_DIGIT+1];
  23. short CMP(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(int i=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. int la=a[0],lb=b[0],d=0;
  40. c[0]=(la>lb?la:lb)+1;
  41. for(int i=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. void SUB(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(int i=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. void MUL(const int *a,const int *b,int *c){//乘法
  73. memset(c,0,sizeof(int)*MAXLEN);
  74. __int64 t=0;
  75. int l = a[0]+b[0]+1;
  76. c[0]=l;
  77. for(int i=1;i<=a[0];i++)
  78. for(int j=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. void MUL(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(int i=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. int la=a[0],lb=b[0],ld=0,min=0,max=0,mid=0,l = la;
  104. double tdmin=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(int i=l;i>0;i--)
  111. {
  112. for(int j=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. int numb[MAXLEN];//具体数字,第0位表示数字长度,第一位及以后分别表示数字的高位至低位
  145. bool flag;
  146. public:
  147. HarInt(){}
  148. ~HarInt(){}
  149. bool Parse(const char *s){
  150. clear();int l=strlen(s),i=0,nl=1;flag = true;//默认为非负数
  151. if(s[0]=='-'){i++;flag = false;}//为负数,数值从第2位开始
  152. for(int j=l-1;j>=i;j-=BASE_DIGIT)
  153. {//从高位至低位一位一位转
  154. int n=0,ten=1;
  155. for(int k=0;(k<BASE_DIGIT&&j-k>=i);k++)
  156. {
  157. if(!IsDigit(s[j-k])){clear();return false;}//含非数字字符,赋值失败
  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. void clear(){memset(numb,0,sizeof(int)*MAXLEN);}
  166. void Parse(const HarInt hi){
  167. memcpy(numb,hi.numb,sizeof(int)*MAXLEN);
  168. flag = hi.flag;
  169. }
  170. void value(const int a){
  171. int t=a;
  172. flag=true;if(t<0){flag=false;t*=-1;}
  173. numb[0]=1;numb[1]=t;
  174. }
  175. int operator[](int i){return numb[i];}
  176. bool Flag(){return flag;}
  177. bool isZero(){return (numb[0]==1&&numb[1]==0);}
  178. int Get(){if(scanf("%s",instr)==EOF)return EOF;return Parse(instr);}
  179. void print(char s){
  180. if(!flag)putchar('-');
  181. printf("%d",numb[numb[0]]);
  182. for(int i=numb[0]-1;i>=1;i--)
  183. printf(PRINTCHAR,numb[i]);
  184. putchar(s);
  185. }
  186. friend short HarIntCmp(HarInt,HarInt);//友元比较函数
  187. friend void DIV(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. else SUB(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. else SUB(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(HarInt a,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(HarInt a,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(int i=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. bool operator<(HarInt a,HarInt b){return (HarIntCmp(a,b)<0);}
  265. bool operator>(HarInt a,HarInt b){return (HarIntCmp(a,b)>0);}
  266. bool operator==(HarInt a,HarInt b){return (HarIntCmp(a,b)==0);}
  267. bool operator!=(HarInt a,HarInt b){return (HarIntCmp(a,b)!=0);}
  268. bool operator<=(HarInt a,HarInt b){return (HarIntCmp(a,b)<=0);}
  269. bool operator>=(HarInt a,HarInt b){return (HarIntCmp(a,b)>=0);}
  270. HarInt operator+(const HarInt& a,const HarInt& b){HarInt c=a;c+=b;return c;}
  271. HarInt operator+(const HarInt& a,const int b){HarInt c;c.value(b);c+=a;return c;}
  272. HarInt operator-(const HarInt& a,const HarInt& b){HarInt c=a;c-=b;return c;}
  273. HarInt operator-(const HarInt& a,const int b){HarInt c;c.value(b);return (a-c);}
  274. HarInt operator*(const HarInt& a,const HarInt& b){HarInt c=a;c*=b;return c;}
  275. HarInt operator*(const HarInt& a,const int b){HarInt c;c.value(b);c*=a;return c;}
  276. HarInt operator/(const HarInt& a,const HarInt& b){HarInt c=a;c/=b;return c;}
  277. HarInt operator/(const HarInt& a,const int b){HarInt c;c.value(b);return (a/c);}
  278. HarInt operator%(const HarInt& a,const HarInt& b){HarInt c=a;c%=b;return c;}
  279. HarInt operator%(const HarInt& a,const int b){HarInt c;c.value(b);return (a%c);}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值