高精度加、减、乘、除算法
高精度运算作用
当参与运算的数据和运算结果的范围超出标准数据类型能表示的数据大小范围的运算时,依靠普通的方法显然不能得到正确的计算结果,因此可以采用高精度算法来进行计算
高精度加法
由于高精度数据的位数较高,因此我们可以用字符串的方法来输入数据,并将字符串转换成数字形式存储到int类型的数据中,对数组进行循环,按位做加法运算,并注意进行进位操作。
由于两个高精度的数(n,m位)做加法的最大位数不会超过他们max(m,n)+ 1,因此在得到相加后的数据时,我们需要注意最后为是否为0,若为0则去掉然后倒序输出即可。
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string str1,str2;
int a[250],b[250],len; //数组的大小决定了计算的高精度最大位数
int i;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>str1>>str2; //输入两个字符串
a[0]=str1.length(); //取得第一个字符串的长度
for(i=1;i<=a[0];i++) //把第一个字符串转换为整数,存放在数组a中
a[i]=str1[a[0]-i]-'0';
b[0]=str2.length(); //取得第二个字符串长度
for(i=1;i<=b[0];i++) //把第二个字符串中的每一位转换为整数,存放在数组B中
b[i]=str2[b[0]-i]-'0';
len=(a[0]>b[0]?a[0]:b[0]); //取两个字符串最大的长度
for(i=1;i<=len;i++) //做按位加法,同时处理进位
{
a[i]+=b[i]; //两数相加
a[i+1]+=a[i]/10; //进行进位操作,进位值为a[i]/10,注意进位是高位的,因此我们要除以10
a[i]%=10; //对相加后的数据进行模10操作,使其取值范围为0-9
}
len++; //下面是去掉最高位的0,然后输出。
while((a[len]==0)&&(len>1)) len--;
for(i=len;i>=1;i--)
cout<<a[i];
return 0;
}
高精度减法
高精度减法相比高精度加法来说,稍微复杂一点,因为减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。
因此我们需要先比较大小,决定输出符号,为正还是为负,然后再按位减法,并注意处理借位
#include<iostream>
#include<cstring>
using namespace std;
bool str_compare(string s1, string s2){
if(s1.length()>s2.length())//s1长度大,则s1>s2
return true;
if(s1.length()<s2.length())//s2长度大,则s1<s2
return false;
for(int i = 0; i < s1.length(); i++){//进行循环按位比较,由于数组存储数据时,高位在数组前面,因此从数组前面开始比较就行
if(s1[i]>s2[i]) return true;
if(s1[i]<s2[i]) return false;
}
return true;//说明相等
}
void sub(int a[], int b[]){
for(int i = 1; i < a[0]; i++){
a[i]-=b[i];
if(a[i]<0){//不够则借位
a[i+1]--;
a[i]+=10;
}
}
a[0]++;
while((a[a[0]]==0)&&(a[0]>1)) a[0]--;//去零
for(int i = a[0]; i>=1; i--)
cout << a[i];
cout << endl;
}
int main(){
string str1,str2;
int a[250],b[250],len;
int i;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>str1>>str2;
a[0]=str1.length();
for(i=1;i<=a[0];i++)
a[i]=str1[a[0]-i]-'0';
b[0]=str2.length();
for(i=1;i<=b[0];i++)
b[i]=str2[b[0]-i]-'0';
if(str_compare(str1, str2)==true){//大于或等于,做按位减
sub(a, b);
}
else{//小于,则注意调换位置
cout <<'-';
sub(b, a);//注意大数减小数
}
}
高精度乘法
与高精度加法类似,通过两个字符串输入两个整数,并将每个整数切割存储到数组里面,然后进行每一位的运算,处理进位,输出结果
#include<iostream>
#include<cstring>
using namespace std;
int main(){
string str1,str2;
int a[250],b[250],c[500],len;
int i,j;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
cin>>str1>>str2;
a[0]=str1.length();
for(i=1;i<=a[0];i++)
a[i]=str1[a[0]-i]-'0';
b[0]=str2.length();
for(i=1;i<=b[0];i++)
b[i]=str2[b[0]-i]-'0';
for(i=1; i<=a[0];i++){
for(j=1; j<=b[0]; j++){
c[i+j-1]+=a[i]*b[j];//按位相乘,注意乘后数的位置
c[i+j]+=c[i+j-1]/10;//处理乘法进位
c[i+j-1]%=10;
}
}
len = a[0] + b[0] + 1;//乘法的结果的数的长度的处理
while((c[len]==0)&&len>1) len--;
for(i = len; i>=1;i--)
cout<<c[i];
cout << endl;
}
高精度除法
高精度除法分为两种情况:
- 第一种情况:高精除以低精,实际上就是对被除的每一位,包括前面的余数都除以除数
#include<iostream>
#include<cstring>
using namespace std;
int main(){
string str1,str3;
int a[250],c[250],len1, len3, i, x=0, b;
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
cin>>str1; //输入高精度被除数
cin>>b; //输入低精度除数
len1=str1.length();
for(i=0;i<len1;i++) //把字符串转换为整数,存放在数组a中
a[i+1]=str1[i]-48;
for(i=1; i<=len1;i++){
c[i] = (x*10 + a[i])/b;//从高到低进行除法运算,注意要加上上一位除法的余数
x = (x*10 + a[i])%b;
}
len3 = 1;
while((c[len3]==0)&&len3<len1) len3++;
for(i = len3; i<=len1;i++)
cout<<c[i];
cout << endl;
}
- 第二种情况:高精除以高精,反复做除法,看从被除数里面最多能减去多少个除数,商就是多少
#include<iostream>
#include<cstring>
using namespace std;
int a[100], b[100], c[100];
int int_compare(int a[], int b[]){//比较a,b的大小,若a>b为1;若a<b为-1;若a=b为0
int i;
if(a[0]>b[0]) return 1;
if(a[0]<b[0]) return -1;
for(i = a[0]; i>0; i--){//从高位到低位比较
if(a[i]>b[i]) return 1;
if(a[i]<b[i]) return -1;
}
return 0;
}
void sub(int a[], int b[]){//计算a=a-b
int flag, i;
flag = int_compare(a, b);
if(flag==0){//相等
a[0] = 0;
return;
}
if(flag==1){//大于
for(i = 1; i<=a[0]; i++){
if(a[i]<b[i]){//不够向上借位
a[i+1]--;
a[i]+=10;
}
a[i]-=b[i];
}
while(a[0]>0&&a[a[0]]==0) a[0]--;
return;
}
}
int main(){
string str1,str2;
int i,j;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
cin>>str1>>str2;
a[0]=str1.length();
for(i=1;i<=a[0];i++)
a[i]=str1[a[0]-i]-'0';
b[0]=str2.length();
for(i=1;i<=b[0];i++)
b[i]=str2[b[0]-i]-'0';
int temp[100];
c[0] = a[0] - b[0] + 1;
for(i=c[0]; i>0;i--){
memset(temp, 0, sizeof(temp));
for(j=1; j<=b[0]; j++)
temp[j+i-1] = b[j];
temp[0]= b[0]+i-1;
while(int_compare(a, temp)>=0){
c[i]++;
sub(a, temp);
}
}
while((c[c[0]]==0)&&c[0]>0) c[0]--;
cout<<"商为: ";
if(c[0]==0)
cout << 0 << endl;
else{
for(i = c[0]; i>0; i--)
cout <<c[i];
cout << endl;
}
cout<<"余数为: ";
if(a[0]==0)
cout << 0 << endl;
else{
for(i = a[0]; i>0; i--)
cout <<a[i];
cout << endl;
}
}