写总结是为了记得更好,力求完善。
大整数加法:
很容易知道,大数输入是用字符串。
所以可以再定义两个数组an1[M +10],an2[M + 10]存放转换之后的大数,需要进行初始化为0,注意存放时应该从个位开始。存完之后开始相加之和存入an1[i],如果an1[i] > 9;an1[i + 1]++。
例题:百炼2981
#include
#include
#define M 200
int an1[M + 10];
int an2[M + 10];
char szLine1[M + 10];
char szLine2[M + 10];
int main()
{
int i,j;
scanf("%s%s",szLine1,szLine2);
memset(an1,0,sizeof(an1));
memset(an2,0,sizeof(an2));
j = 0;
for(i = strlen(szLine1) - 1;i >= 0; i--)
an1[j++] = szLine1[i] - '0';
j = 0;
for(i = strlen(szLine2) - 1;i >= 0; i--)
an2[j++] = szLine2[i] - '0';
for(i = 0;i < M; i++){
an1[i] += an2[i];
if(an1[i] >= 10){
an1[i] -= 10;
an1[i + 1]++;
}
}
bool flag = false;
for(i = M;i >= 0; i--) //也可以删除0 = M
if(flag)
printf("%d",an1[i]);
else if(an1[i]){
printf("%d",an1[i]);
flag = 1;
}
if(flag == false) //注意0+0的情况
printf("0\n");
printf("\n");
return 0;
}
例题:POJ1503
这道题是;连续输入大数,直到输入到0。
法一:
还是按着之前的套路来,开数组,初始化,字符转化到数组,相加,输出。
#include
#include
#define M 105
int an1[M + 10];
int an2[M + 10];
char szLine[M + 10];
int main()
{
int i,j,length;
memset(an1,0,sizeof(an1));
while(scanf("%s",szLine) != EOF){
memset(an2,0,sizeof(an2));
length = strlen(szLine);
j = 0;
for(i = length - 1;i >= 0; i--)
an2[j++] = szLine[i] - '0';
for(i = 0;i < M; i++){
an1[i] += an2[i];
if(an1[i] > 9){
an1[i] -= 10;
an1[i + 1]++;
}
}
bool flag = false;
if(strcmp(szLine,"0") == 0){
for(i = M;i >= 0; i--)
if(flag)
printf("%d",an1[i]);
else if(an1[i]){
printf("%d",an1[i]);
flag = true;
}
printf("\n");
memset(an1,0,sizeof(an1));
}
}
return 0;
}
#include
#include
#define M 105
int main()
{
int i,an1[M + 10] = {0},length;
char szLine[M + 10];
while(scanf("%s",szLine) != EOF){
length = strlen(szLine);
int k = M;
for(i = length - 1;i >= 0; i--){ //直接进行倒着运算,M为个位
an1[k] += szLine[i] - '0';
if(an1[k] > 9){
an1[k] -= 10;
an1[k - 1]++;
}
k--;
}
if(strcmp(szLine,"0") == 0){
for(i = 0;i <= M; i++)
if(an1[i]) break;
for( ;i <= M; i++)
printf("%d",an1[i]);
printf("\n");
memset(an1,0,sizeof(an1));
}
}
return 0;
}
大数相乘:大部分算法都和大数相加一样,开两个数组an1[M + 10从,an2[M + 10]个位存放大数,不同的是乘法在计算的时候需要an2[i]去乘以an1的每一位,乘的结果累加到新开的数组aResult[i+j];这里有一个规律就是一个数的第i为位和另一个数相乘的结果一定要累加到第i+j位。比如16*12,第一次用an2[0]乘以an1[0]得到aResult[0 + 0] = 12,an[0]*an1[1] = 2;第二次an2[1]*an1[0] = 6累加到aResult[1+0]中得8,an2[1]*an1[1] = 1,累加到aResult[2]得到1;这样aResult中个位十位百位分别为12,8,1;然后统一处理进位问题得到2,9,1;结果便是192。
例题:百炼2980
#include
#include
#define M 200
int an1[M + 10];
int an2[M + 10];
int aResult[M*2 + 10];
char szLine1[M + 10];
char szLine2[M + 10];
int main()
{
int i,j;
scanf("%s%s",szLine1,szLine2);
int length1,length2;
length1 = strlen(szLine1);
length2 = strlen(szLine2);
memset(an1,0,sizeof(an1));
memset(an1,0,sizeof(an2));
memset(aResult,0,sizeof(aResult));
j = 0;
for(i = length1 - 1;i >= 0; i--)
an1[j++] = szLine1[i] - '0';
j = 0;
for(i = length2 - 1;i >= 0; i--)
an2[j++] = szLine2[i] - '0';
for(i = 0;i < length2; i++)
for(j = 0;j < length1; j++)
aResult[j + i] += an1[j] * an2[i]; //注意累加
for( i = 0;i < M*2; i++)
if(aResult[i] > 9){
aResult[i + 1] += aResult[i]/10; //注意累加
aResult[i] %= 10;
}
bool flag = false;
for(i = M*2;i >= 0; i--)
if(flag)
printf("%d",aResult[i]);
else if(aResult[i]){
printf("%d",aResult[i]);
flag = true;
}
if(!flag)
printf("0\n");
printf("\n");
return 0;
}
对于这种复杂的高精度处理要条理清晰。最后的核心算法都是套路。
/*需要注意的点太多了,没事就多打几遍*/
#include
#include
#include
using namespace std;
int point;
void ridzero(char a[])
{
int i;
i = strlen(a) - 1;
while(a[i] == '0'){
a[i] = '\0';
i--;
}
}
void ridpoint(char a[])
{
int i,length;
length = strlen(a);
for(i = 0;i < length; i++) //判断是否有小数点
if(a[i] == '.')
break;
if(i != length){
for(i = length - 1;i >= 1; i--) //记录小数点的位置
if(a[i] != '.') point ++;
else break;
if(a[0] == '0'){ //小数点有两种情况,一是0.0***的形式,去除小数点
for(i = 2;i < length; i++)
if(a[i] != '0'){
strcpy(a,&a[i]);
break;
}
}
else { //这是***.**的形式,去除小数点
int flag = 0;
for(i = 1;i < length - 1; i++){
if(a[i] == '.') flag = 1;
if(flag) a[i] = a[i + 1];
}
a[i] = '\0';
}
}
}
void multiplication(char a[],char b[])
{
int length1 = strlen(a),length2 = strlen(b);
int i,j,an1[210],an2[210],aResult[420];
memset(an1,0,sizeof(an1));
memset(an2,0,sizeof(an2));
memset(aResult,0,sizeof(aResult));
j = 0;
for(i = strlen(a) - 1;i >= 0; i--)
an1[j++] = a[i] - '0';
j = 0;
for(i = strlen(b) - 1;i >= 0; i--)
an2[j++] = b[i] - '0';
for(i = 0;i < length2; i++)
for(j = 0;j < length1; j++)
aResult[i + j] += an1[j] * an2[i];
for(i = 0;i < 410; i++)
if(aResult[i] >= 10){
aResult[i + 1] += aResult[i]/10;
aResult[i] %= 10;
}
bool flag = false;
j = 0;
for(i = 410;i >= 0; i--)
if(flag) a[j++] = aResult[i] + '0';
else if(aResult[i]){
a[j++] = aResult[i] + '0';
flag = 1;
}
a[j] = '\0';
}
void show(char a[])
{
int i,length;
length = strlen(a);
if(point >= length){
printf(".");
for(i = point - length;i > 0; i--)
printf("0");
printf("%s\n",a);
}
else {
for(i = 0;i < length; i++)
if(length - point == i){
cout<<"."<<&a[i];
break;
}
else cout<>str1>>n){
if(n == 0){
printf("1\n");
continue;
}
point = 0;
ridzero(str1); //去掉多余的零
ridpoint(str1); //去掉小数点
strcpy(str2,str1);
for(i = 1;i < n; i++)
multiplication(str1,str2); //核心算法,大数相乘
point *= n; //记录小数点的位置
show(str1);
}
return 0;
}