简单介绍高精度算法

我们知道,整型变量所储存的数的大小是有限的。但有时,我们却需要进行更大数据量的运算(如计算2^10000),这时,我们便需要使用高精度算法来实现它们之间的加减乘除等运算。

基本思想

首先是数的储存。我们使用数组来储存变量,数组的每一位储存这个数的每一位。我们可以使用整形数组或者字符串来储存,这里使用字符串来储存,因此会有一些较为恶心的字符和整形间的转换。

之后是数的运算。我们可以很方便的调用一个数的某一位,我们便通过模拟数学上列竖式计算的过程来实现两个数之间的加减乘除运算。

可以看出来,这是一个没有理解难度,但实现起来异常繁琐的算法:)

代码

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 
  6 using namespace std;
  7 
  8 string a,b,c,d;
  9 
 10 int comp(string x,string y);
 11 void swap(string &x,string &y);
 12 string add(string x,string y);
 13 string sub(string x,string y);
 14 string mul(string x,string y);
 15 void div(string x,string y,string &quo,string &res);
 16 
 17 int main()
 18 {
 19     cin>>a>>b;
 20     
 21     div(a,b,c,d);
 22     
 23     cout<<c<<endl<<d;
 24     return 0;
 25 }
 26 
 27 //比较两数的大小,前者大返回1,反之返回-1,相等返回0 
 28 int comp(string x,string y)
 29 {
 30     if(x.length()>y.length()) return 1;
 31     else if(x.length()<y.length()) return -1;
 32     else return x.compare(y);
 33 }
 34 
 35 //交换两数位置 
 36 void swap(string &x,string &y)
 37 {
 38     string z=x;
 39     x=y;
 40     y=z;
 41 }
 42 
 43 //高精度加法,两数需都是正数且是整数 
 44 string add(string x,string y)
 45 {
 46     string ans;
 47     if(comp(x,y)==-1) swap(x,y);
 48     int len1=x.length();
 49     int len2=y.length();
 50     
 51     for(int i=1;i<=len1-len2;i++) y="0"+y;//较短数补0使两数位数相等 
 52     
 53     int cf=0,temp;//cf是进位,temp是相加后本位数 
 54     for(int i=len1-1;i>=0;i--)//核心部分 
 55     {
 56         temp=(x[i]-'0')+(y[i]-'0')+cf;
 57         cf=temp/10;
 58         temp%=10;
 59         ans=char(temp+'0')+ans;
 60     }
 61     if(cf) ans=char(cf+'0')+ans;//如果仍有进位,加到最前方 
 62     
 63     return ans;
 64 }
 65 
 66 //高精度减法,两数需都是正数且是整数,默认调整为大减小 
 67 string sub(string x,string y)
 68 {
 69     string ans;
 70     if(comp(x,y)==-1) swap(x,y);
 71     int tmp=x.length()-y.length();
 72     int cf=0;
 73     
 74     for(int i=y.length()-1;i>=0;i--)//两数共有位的相减 
 75     {
 76         if(x[tmp+i]-cf<y[i])
 77         {
 78             ans=char(x[tmp+i]-y[i]-cf+'0'+10)+ans;
 79             cf=1;//进位1 
 80         }
 81         else
 82         {
 83             ans=char(x[tmp+i]-y[i]-cf+'0')+ans;
 84             cf=0;//不进位 
 85         }
 86     }
 87     for(int i=tmp-1;i>=0;i--)//大数专有位的相减 
 88     {
 89         if(x[i]-cf>='0')
 90         {
 91             ans=char(x[i]-cf)+ans;
 92             cf=0;
 93         }
 94         else
 95         {
 96             ans=char(x[i]-cf+10)+ans;
 97             cf=1;
 98         }
 99     }
100     ans.erase(0,ans.find_first_not_of('0'));//去除答案前的0 
101     if(ans.empty()) ans="0";//如果去0后答案为空,赋给0 
102     return ans;
103 }
104 
105 // 高精度乘法,两数需都是正数且是整数,需用到高精度加法 
106 string mul(string x,string y)
107 {
108     string ans;
109     int len1=x.length();
110     int len2=y.length();
111     string tempstr;
112     
113     for(int i=len2-1;i>=0;i--)
114     {
115         tempstr="";//tempstr是单位相乘得到的结果 
116         int temp=y[i]-'0';//temp是此位数 
117         int t=0,cf=0;// t是相乘后本位数,cf是进位 
118         
119         if(temp)
120         {
121             for(int j=1;j<=len2-1-i;j++) tempstr+="0";//模拟乘法竖式里的错位 
122             for(int j=len1-1;j>=0;j--)//核心部分 
123             {
124                 t=(temp*(x[j]-'0')+cf)%10;
125                 cf=(temp*(x[j]-'0')+cf)/10;
126                 tempstr=char(t+'0')+tempstr;
127             }
128             if(cf) tempstr=char(cf+'0')+tempstr;//如果仍有进位,加到最前方 
129         }
130         ans=add(ans,tempstr);
131     }
132     ans.erase(0,ans.find_first_not_of('0'));//去除答案前的0 
133     if(ans.empty()) ans="0";//如果去0后答案为空,赋给0 
134     return ans;
135 }
136 
137 // 高精度除法,两数需都是正数且是整数,需用到高精度乘法(也就是还会用到高精度加法),高精度减法 
138 void div(string x,string y,string &quo,string &res)//quo是商(quotient),res是余数(residue) 
139 {
140     quo=res="";
141     if(y=="0")//一些很好理解的特殊情况 
142     {
143         quo=res="ERROR";
144         return;
145     }
146     if(x=="0")
147     {
148         quo=res="0";
149         return;
150     }
151     int com=comp(x,y);
152     if(com==-1)
153     {
154         quo="0";
155         res=x;
156         return;
157     }
158     if(com==0)
159     {
160         quo="1";
161         res="0";
162         return;
163     }
164     if(com==1)//当x比y大时 
165     {
166         int len1=x.length();
167         int len2=y.length();
168         string tempstr;//tempstr现在是被除的那几位数
169         tempstr.append(x,0,len2-1);
170         for(int i=len2-1;i<len1;i++)
171         {
172             tempstr=tempstr+x[i];//相减后的结果补位 
173             tempstr.erase(0,tempstr.find_first_not_of('0'));
174             if(tempstr.empty()) tempstr="0";
175             for(char ch='9';ch>='0';ch--)//从大到小试商 
176             {
177                 string str,tmp;//str是试出的商,tmp是相乘后的结果 
178                 str=str+ch;
179                 tmp=mul(y,str);
180                 if(comp(tmp,tempstr)<=0)
181                 {
182                     quo=quo+ch;
183                     tempstr=sub(tempstr,tmp);//tempstr现在是相减后的结果
184                     break;
185                 }
186             }
187         }
188         res=tempstr;//余数等于余下的相减后的结果
189     }
190     quo.erase(0,quo.find_first_not_of('0'));//去除商前的0 
191     if(quo.empty()) quo="0";//如果余数为空,赋给0
192     return;
193 }

 

posted @ 2020-11-10 09:09  CYHei_mu  阅读(237)  评论(0)    收藏  举报