转载出处: http://www.cnblogs.com/ECJTUACM-873284962/
参考:https://blog.youkuaiyun.com/fanyun_01/article/details/79967170
前言:由于计算机运算是有模运算,数据范围的表示有一定限制,如整型int(C++中int 与long相同)表达范围是(-2^31~2^31-1),unsigned long(无符号整数)是(0~2^32-1),都约为几十亿.如果采用实数型,则能保存最大的double只能提供15~16位的有效数字,即只能精确表达数百万亿的数.因此,在计算位数超过十几位的数时,不能采用现有类型,只能自己编程计算.
高精度计算通用方法:高精度计算时一般用一个数组来存储一个数,数组的一个元素对应于数的一位(当然,在以后的学习中为了加快计算速度,也可用数组的一个元素表示数的多位数字,暂时不讲),表示时,由于数计算时可能要进位,因此为了方便,将数由低位到高位依次存在数组下标对应由低到高位置上,另外,我们申请数组大小时,一般考虑了最大的情况,在很多情况下,表示有富余,即高位有很多0,可能造成无效的运算和判断,因此,我们一般将数组的第0个下标对应位置来存储该数的位数.如数:3485(三千四百八十五),表达在数组a[10]上情况是:
下标 0 1 2 3 4 5 6 7 8 9
内容 4 5 8 4 3 0 0 0 0 0
说明:位数 个位 十位 百位 千位
具体在计算加减乘除时方法就是小学时采用的列竖式方法.
注:高精度计算时一般用正数,对于负数,通过处理符号位的修正.
一 . 高精度数的存储
1.如对数采用的字符串输入
#include<iostream>
using namespace std;
const int N = 200;
int main()
{
int a[N+1],i;
string s1;
cin >> s1;
memset(a, 0, sizeof(a));
a[0] = s1.length();
for( i = 1; i <= a[0]; i++)
a[i] = s1[a[0] - i] - '0';
return 0;
}
二 . 高精度数比较
int Compare(int a[], int b[])
{
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;
}
三 . 高精度数相加
int Plus (int a[], int b[])
{
int i, k;
k = a[0] > b[0] ? a[0] : b[0];
for( i = 1;i <= k; i++)
{
a[i+1] += (a[i] + b[i]) / 10;
a[i] = (a[i] + b[i]) % 10;
}
if(a[k+1] > 0)
a[0] = k+1;
else
a[0] = k;
return 0;
}
四 . 高精度数减法
int Subtraction(int a[], int b[])
{
int flag ,i;
flag = Compare(a,b);
if(flag == 0)
{
memset(a, 0, sizeof(a));
return 0;
}
if(flag == 1)
{
for( i = 1;i <= a[0]; i++)
{
if(a[i] < b[i])
{
a[i+1]--;
a[i] += 10;
}
a[i] = a[i] - b[i];
}
while(a[a[0]] == 0) a[0]--;
return 0;
}
if(flag == -1)
{
for(i = 1;i <= b[0]; i++)
{
if(b[i] < a[i])
{
b[i+1]--;
b[i] += 10;
}
a[i] = b[i] - a[i];
}
a[0] = b[0];
while(a[a[0]] == 0) a[0]--;
return -1;
}
}
五 . 高精度数乘法
1 . 高精度乘低精度
int Multi(int a[],long key)//高精度 乘以低精度 a= a*key
{
int i,k;
if( key == 0)
{
memset(a, 0,sizeof(a));
a[0] = 1;
return 0;
}
for( i = 1;i <= a[0];i++)
a[i] = a[i] * key;
for( i = 1;i <= a[0]; i++)
{
a[i+1] += a[i]/10 ;
a[i] %= 10;
}
while (a[a[0] + 1] > 0)
a[0]++;
return 0;
}
2. 高精度乘高精度
int main()
{
int a[N+1], i, len, b[N+1], c[2*N+5];
string s1, s2;
cin >> s1 >> s2 ;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
a[0] = s1.length();
b[0] = s2.length();
for( i = 1; i <= a[0]; i++)
a[i] = s1[a[0] - i] - '0';
for( i = 1; i <= b[0]; i++)
b[i] = s2[b[0] - i] - '0';
for(i = 1; i <= a[0]; i++)
for(int 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; //去掉最高位的0,然后输出
while((c[len]==0)&&(len>1)) len--; //为什么此处要len>1??
c[0] = len;
for(i = c[0]; i >= 1; i--)
cout << c[i];
return 0;
}
六 . 高精度除法
1. 高精度除低精度
#include <stdio.h>
#define N 500
main()
{
int a[N] = {0}, c[N] = {0};
int i, k, d, b;
char a1[N];
printf("Input 除数:");
scanf("%d", &b);
printf("Input 被除数:");
scanf("%s", a1);
k = strlen(a1);
for(i = 0; i < k; i++) a[i] = a1[k - i - 1] - '0';
d = 0;
for(i = k - 1; i >= 0 ; i--)
{
d = d * 10 + a[i];
c[i] = d / b;
d = d % b;
}
while(c[k - 1] == 0 && k > 1) k--;
printf("商=");
for(i = k - 1; i >= 0; i--) printf("%d", c[i]);
printf("\n余数=%d", d);
}
代码2
int Devision(int a[], int b,int c[]) //c[]存商,a[]被除数,b除数
{
int i;
int d = 0;
c[0] = a[0];
for(i = a[0]; i >= 1;i--)
{
d = d * 10 + a[i];
c[i] = d / b;
d = d % b;
}
while(c[0] == 0 && c[0] > 1) c[0]--;
if(d == 0) //余数为0
return 1;
else
return 0;
}
2. 高精度除以高精度
#include<iostream>
#include<cstring>
using namespace std;
int a[100],b[100],c[100];
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 subduction(int a[],int b[])//计算a=a-b
{
int flag;
int i;
flag=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)//删除前导0
a[0]--;
return;
}
}
int main()
{
char str1[100],str2[100];
int i,j;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
cin>>str1>>str2;
a[0]=strlen(str1);//a[0]存储串1的位数
b[0]=strlen(str2);//b[0]存储串2的位数
for(i=1;i<=a[0];i++)
a[i]=str1[a[0]-i]-'0';
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++)//从i开始的地方,复制数组b到数组temp
temp[j+i-1]=b[j];
temp[0]=b[0]+i-1;
while(compare(a,temp)>=0)//用减法模拟
{
c[i]++;
subduction(a,temp);
}
}
while(c[0]>0&&c[c[0]]==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;
}
return 0;
}