从零步步行-基础算法-高精度算法

        高精度算法题就是指简单的加减乘除题,但是加减的数据极大,无法用int、long long等数据类型表示,因此可以通过字符数组来表示,再转换为整形数组运算。(该类题型一般作为基础运用于较难的运算题目中)

一、高精度算法题之加(减):

例题:(减也大差不差)

A + B Problem II

时间限制(普通/Java):1000MS/10000MS 内存限制:65536KByte

描述

I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B.

输入

The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.

输出

For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line is the an equation "A + B = Sum", Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.

样例输入

2
1 2
112233445566778899 998877665544332211

样例输出

Case 1:
1 + 2 = 3

Case 2:
112233445566778899 + 998877665544332211 = 1111111111111111110

题目注意点:

1.注意数组的初始化,不对数组再次归零会出错;

2.字符数组转整形数组容易出错;

3.注意入录数组后的数字顺序,在计算时容易出现错误;

4.注意的范围与顺序;


AC代码:

#include<bits/stdc++.h>
using namespace std;
char xc[1005]={0},yc[1005]={0};
int x[1005]={0},y[1005]={0},z[1005]={0};		// 定义字符数组xc和yc来存储输入的整数,整数数组x、y和z来存储转换后的整数
int l;		//用于存储数组长度

// 定义函数Add,用于执行大整数加法。函数内部使用循环来处理每一位的加法,并处理可能的进位
void Add(){
    for(int j=0;j<l;j++){
        z[j]+=x[j]+y[j];
        z[j+1]+=z[j]/10;	// 计算进位,并存储在z[j+1]中
        z[j]=z[j]%10;		// 计算z[j]的个位数,并存储在z[j]中
    	//运行错误时,可以在以下的printf来判断自己的错误点 (这也是wrong时修改题目的技巧) 
		//printf("j=%d x[j]=%d y[j]=%d z[j]=%d z[j+1]=%d\n",j,x[j],y[j],z[j],z[j+1]);
	}
    if(z[l]>0) l++;		// 如果z[l]大于0,说明还有进位,需要额外处理
    return;
}


int main(){
    int t,lx,ly;
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%s%s",&xc,&yc);
        lx=strlen(xc);
        ly=strlen(yc);
        l=max(lx,ly);		// 对于每个测试用例,读取两个整数,并计算它们的长度,然后获取长度较大的那个作为l
        for(int j=0;j<lx;j++)
            x[lx-j-1]=xc[j]-'0';
        for(int j=0;j<ly;j++)
            y[ly-j-1]=yc[j]-'0';
        // 将字符数组转换为整数数组
        Add();
        // 调用Add函数执行加法
        printf("Case %d:\n",i);
        printf("%s + %s = ",xc,yc);
        for(int j=l-1;j>=0;j--){
            printf("%d",z[j]);
            // 每次输出后,将x[j]、y[j]和z[j]清零,以便下一次测试用例使用
            x[j]=y[j]=z[j]=0;
        }
        // 输出结果,并在每个测试用例之间输出一个空行
        if(i!=t) printf("\n\n");
    }
    return 0;
}

二、高精度算法题之乘:

高精度乘法

时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte

描述

输入两个高精度非负整数M和N(M和N均小于100位)。求这两个高精度数的积。

输入

输入两个高精度非负整数M和N。

输出

求这两个高精度数的积,结果不含前导0。

样例输入

36
3

样例输出

108

题目注意点:

1.注意结果的储存数组要大,不同于加减;

2.乘除运算方法与加减的巨大不同;

3.结果数组的长度为俩乘数数组的相加,并不断减小;(例如两个二位数相乘可以为四位数也可以为三位数)

提示:

AC代码:

#include<bits/stdc++.h>
using namespace std;
char xc[105]={0},yc[105]={0};
int x[105]={0},y[105]={0},z[100005]={0};
int l,lx,ly;
// 定义字符数组xc和yc来存储输入的整数,整数数组x、y和z来存储转换后的整数,以及整数l来存储数组长度

void Multiply(){
    for(int j=0;j<lx;j++){		// 遍历x数组的每一位
        for(int k=0;k<ly;k++){		// 遍历y数组的每一位
            z[j+k]+=x[j]*y[k];
            z[j+k+1]+=z[j+k]/10;
            z[j+k]%=10;
        }
    }
    while(l&&z[l]==0) l--;		// 存余,且存在乘数为0的可能,所以要加l 
    return;
}
// 定义函数Multiply,用于执行高精度乘法。函数内部使用两层循环来处理每一位的乘法,并处理可能的进位

int main(){
    scanf("%s%s",&xc,&yc);
    lx=strlen(xc);
    ly=strlen(yc);
    l=lx+ly;
    for(int j=0;j<lx;j++)
        x[lx-j-1]=xc[j]-'0';
    for(int j=0;j<ly;j++)
        y[ly-j-1]=yc[j]-'0';
    Multiply();
    for(int j=l;j>=0;j--){
        printf("%d",z[j]);
        x[j]=y[j]=z[j]=0;
    }
    return 0;
}

三、高精度算法题之除:

高精除

时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte

描述

高精除以高精,求它们的商和余数。

输入

输入两个低于300位的正整数。

输出

输出商和余数。

样例输入

1231312318457577687897987642324567864324567876543245671425346756786867867867
1231312318767141738178325678412414124141425346756786867867867

样例输出

999999999748590
179780909068307566598992807564736854549985603543237528310337

题目提示:

1.主要要注意运算的是第几位;

2.关键点较多,看代码和解析吧;(代码写的好累,下次有空再补注意点吧)

AC代码:

#include<bits/stdc++.h>
using namespace std;

const int N=305; // 定义常量N为305,用于数组的长度
char xc[N]={0},yc[N]={0}; // 定义字符数组xc和yc,用于存储输入的整数,初始化为0
int x[N]={0},y[N]={0},z[N]={0},q[N]={0}; // 定义整数数组x、y、z和q,用于存储转换后的整数
int l,lx,ly; // 定义整数l、lx和ly,用于存储数组长度

// 函数Can用于判断是否可以减去除数
bool Can(int j){
    if(x[j+ly]>0){ // 如果被除数的下一位大于0,返回true
        return true;
    }
    for(int i=ly-1;i>=0;i--){ // 从除数的最高位开始,逐位比较
        if(x[j+i]<y[i]) return false; // 如果被除数小于除数,返回false
        else if(x[j+i]>y[i]) return true; // 如果被除数大于除数,返回true
    }
    return true; // 如果相等,返回true
} 

// 函数Multiply用于执行除法操作
void Multiply(){
    for(int i=l-1;i>=0;i--){ // 从被除数的最高位开始,逐位进行除法操作
        while(Can(i)){ // 如果可以减去除数
            z[i]++; // 商加1
            for(int j=0;j<ly;j++){ // 逐位执行减法操作
                if(x[i+j]>=y[j]) x[i+j]-=y[j]; // 如果被除数大于等于除数,直接相减
                else{ // 如果被除数小于除数,需要借位
                    x[i+j+1]--; // 高位减1
                    x[i+j]+=10-y[j]; // 当前位加10再减去除数的对应位
                }
            }
        }
    }
    return ;
}

int main(){
    scanf("%s%s",&xc,&yc); // 输入两个整数,作为字符串
    lx=strlen(xc); // 计算第一个整数的长度
    ly=strlen(yc); // 计算第二个整数的长度
    l=lx-ly+1; // 计算商的长度
    for(int j=0;j<lx;j++) x[lx-j-1]=xc[j]-'0'; // 将第一个整数转换为整数数组
    for(int j=0;j<ly;j++) y[ly-j-1]=yc[j]-'0'; // 将第二个整数转换为整数数组
    Multiply(); // 调用Multiply函数执行除法操作
    int f=1; // 定义变量f,用于判断是否有前导零
    for(int j=lx-1;j>=0;j--){ // 输出商
        if(!f||z[j]>0){ // 如果不是前导零或者当前位大于0
            printf("%d",z[j]); // 输出当前位
            z[j]=0; // 将当前位清零
            f=0; // 标记为没有前导零
        }
    }
    if(f) printf("0"); // 如果所有位都是前导零,输出0
    printf("\n"); // 输出换行符
    f=1; // 重置变量f,用于判断余数的前导零
    for(int j=lx-1;j>=0;j--){ // 输出余数
        if(!f||x[j]>0){ // 如果不是前导零或者当前位大于0
            printf("%d",x[j]); // 输出当前位
            x[j]=0; // 将当前位清零
            f=0; // 标记为没有前导零
        }
    }
    if(f) printf("0"); // 如果所有位都是前导零,输出0
    return 0;
}

结束语:

        作为一个萌新,想着记录一下学习的一点点进度,并且给大家分享一下我的想法。作为第一篇博客,希望读者大大能给点改良的建议哦,Thanks♪(・ω・)ノ

        也希望能为你们提供到一些帮助,如果有帮助的话,给个免费的三连吧

        爱你(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值