简单介绍高精度算法
我们知道,整型变量所储存的数的大小是有限的。但有时,我们却需要进行更大数据量的运算(如计算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 }

浙公网安备 33010602011771号