C++大整数加法(易懂)

1.代码思路

在我们做加法时,一定是先把他们的最后一位对齐,然后从最后一位数开始相加,如果相加的结果大于9,那么就在前一位加好的基础上再加1

2.代码详解

2.1 完整代码

#include <iostream>
#include <cstring>
using namespace std;

int addzero(char one[], char two[], int lenone, int lentwo);

int main() {
    int a = 0, num = 0, addone = 0, max = 0, min = 0, b = 0;
    static char one[1001];
    static char two[1001];

    gets(one);
    gets(two);

    int lenone = strlen(one);
    int lentwo = strlen(two);
    addzero(one, two, lenone, lentwo);
    lenone=strlen(one);
    lentwo=strlen(two);
    int f[lentwo];
    int k=lentwo-1;
    for (int i = lenone - 1; i >= 0; i--) {
        num = int(one[i]) - 48 + int(two[i]) - 48 + a;
        if (num > 9) {
            num = num - 10;
            a = 1;
        } 
        else {
            a = 0;
        }
        f[k]=num;
        k--;
        if (i==1 && a==1){
            b=0;
        }
        if (i==1 && a==0){
            b=1;
        }
    }   
    k=lentwo;
    for (int i=b;i<k;i++){
        cout << f[i];
    }
    return 0;
}

int addzero(char one[], char two[], int lenone, int lentwo) {
    char b=0;
    int zero=0;

    if (lenone==lentwo){
        for (int i=1;i <= lenone;i++) {
            b=one[lenone-i];
            one[lenone-i+1] = b;
        }
        one[0] = '0';
        for (int i=1;i <= lentwo;i++) {
            b=two[lentwo-i];
            two[lentwo-i+1] = b;
        }
        two[0] = '0';
        b=0;
    }

    if (lenone>lentwo){
        for (int i=1;i <= lenone;i++){
            b=one[lenone-i];
            one[lenone-i+1] = b;
        }
        one[0] = '0';
        for (int i=1;i <= lentwo;i++){
            b=two[lentwo-i];
            two[lentwo-i+(lenone-lentwo)+1] = b;
            zero=lenone-lentwo;
        }
        for (int i=zero;i>=0;i--){
            two[i]='0';
        }
        b=0,zero=0;
    }

    if (lentwo>lenone){
        for (int i=1;i <= lentwo;i++){
            b=two[lentwo-i];
            two[lentwo-i+1] = b;
        }
        two[0] = '0';
        for (int i=1;i <= lenone;i++){
            b=one[lenone-i];
            one[lenone-i+(lentwo-lenone)+1] = b;
            zero=lentwo-lenone;
        }
        for (int i=zero;i>=0;i--){
            one[i]='0';
        }
        b=0,zero=0;
    }
    return 0;
}

2.2 addzero函数

先来解释一下b和zero这两个变量的含义:b用于将数组整体向后移动时记录数组数字的变量,同时方便像新手解释

zero用于记录要往这个数组中添加多少个0

,,

if (lenone==lentwo){
        for (int i=1;i <= lenone;i++) {
            b=one[lenone-i];
            one[lenone-i+1] = b;
        }
        one[0] = '0';
        for (int i=1;i <= lentwo;i++) {
            b=two[lentwo-i];
            two[lentwo-i+1] = b;
        }
        two[0] = '0';
        b=0;
    }

当两个加数长度相等时,我们要在这两个加数的前面个加上一个'0'

我们用b来记录我们要移动的那一位,然后将b赋值给原本b的后面一位。

下面我来模拟一下(两个加数长度相同时):

one = [143]
two = [714]

lenone = 3
lentwo = 3

第一次循环:
b = one[lenone - i] = one[3 - 1] = one[2] = 3
one = [1433]

第二次循环:
b = one[lenone - i] = one[3 - 2] = one[1] = 4
one = [1443]

第三次循环:
b = one[lenone - i] = one[3 - 3] = one[0] = 1
one = [1143]

循环结束
one[0] = '0'
one = [0143]

这样第一个加数添加'0'的步骤就完成了,第二个加数同理

if (lenone>lentwo){
        for (int i=1;i <= lenone;i++){
            b=one[lenone-i];
            one[lenone-i+1] = b;
        }
        one[0] = '0';
        for (int i=1;i <= lentwo;i++){
            b=two[lentwo-i];
            two[lentwo-i+(lenone-lentwo)+1] = b;
            zero=lenone-lentwo;
        }
        for (int i=zero;i>=0;i--){
            two[i]='0';
        }
        b=0,zero=0;
    }

当第一个加数的长度大于第二个加数的长度时,第一个加数还是像刚才一样在最前面加上一个'0',就不过多解释了。

我们来看第二个加数,我们还是把要向后移的那一位赋值给b,至于向后多少位,我们并不能知道确切的数字,但为了保持加完'0'之后两个加数的长度相同,所以除了向后移一位,还要再向后移两个加数长度差位,移动完成后,zero储存的值是两个加数的长度差。这样说可能不太容易理解,我来给大家示范一下:

第一个加数的移动就不过多演示了,我们来看第二个加数

one = [5262]
two = [153]

lenone = 4
lentwo = 3

第一次循环:
b = two[lentwo - i] = two[3 - 1] = two[2] = 3
lentwo - i + (lenone - lentwo) + 1 = 3 - 1 + 1 + 1 = 4
153 3

第二次循环:
b = two[lentwo - i] = two[3 - 2] = two[1] = 5
lentwo - i + (lenone - lentwo) + 1 = 3 - 2 + 1 + 1 = 3
15353

第三次循环:
b = two[lentwo - i] = two[3 - 3] = two[0] = 1
lentwo - i + (lenone - lentwo) + 1 = 3 - 3 + 1 + 1 = 2
15153

循环结束

zero = lenone - lentwo = 4 - 3 = 1

下一个循环:
第一次循环:
two[i](two[1]) = '0'
10153

第二次循环:
two[i](two[0]) = '0'
00153

循环结束

假设one数组我们也添加好'0'了,现在两个数组变成了这样:
one = [05262]
two = [00153]

if (lentwo>lenone){
        for (int i=1;i <= lentwo;i++){
            b=two[lentwo-i];
            two[lentwo-i+1] = b;
        }
        two[0] = '0';
        for (int i=1;i <= lenone;i++){
            b=one[lenone-i];
            one[lenone-i+(lentwo-lenone)+1] = b;
            zero=lentwo-lenone;
        }
        for (int i=zero;i>=0;i--){
            one[i]='0';
        }
        b=0,zero=0;
    }

同理,这一段代码与上一段极为相似,只是把所有的'one'替换成了'two','two'替换成了'one'

2.3 main函数

int main() {
    int a = 0, num = 0, addone = 0, max = 0, min = 0, b = 0;
    static char one[1001];
    static char two[1001];

    gets(one);
    gets(two);

    int lenone = strlen(one);
    int lentwo = strlen(two);
    addzero(one, two, lenone, lentwo);
    lenone=strlen(one);
    lentwo=strlen(two);
    int f[lentwo];
    int k=lentwo-1;
    for (int i = lenone - 1; i >= 0; i--) {
        num = int(one[i]) - 48 + int(two[i]) - 48 + a;
        if (num > 9) {
            num = num - 10;
            a = 1;
        } 
        else {
            a = 0;
        }
        f[k]=num;
        k--;
        if (i==1 && a==1){
            b=0;
        }
        if (i==1 && a==0){
            b=1;
        }
    }   
    k=lentwo;
    for (int i=b;i<k;i++){
        cout << f[i];
    }
    return 0;
}

这些变量在后续使用的时候会做讲解。static的作用是让它在两个函数中均可使用。

lenone和lentwo储存的是这两个数组的长度,然后调用addzero函数进行预处理。f数组储存最后的计算结果。

下面我们来看main函数中最主要的循环:

for (int i = lenone - 1; i >= 0; i--) {
        num = int(one[i]) - 48 + int(two[i]) - 48 + a;
        if (num > 9) {
            num = num - 10;
            a = 1;
        } 
        else {
            a = 0;
        }
        f[k]=num;
        k--;
        if (i==1 && a==1){
            b=0;
        }
        if (i==1 && a==0){
            b=1;
        }
    }   

(注意:此时我们已经完成预处理,现在两个加数的长度相等)

首先,你应该知道,在进行加法运算时是从最后一位开始计算,所以这个循环的循环变量的初识值为加数最后一位的下标数(即lenone - 1),我们必须要计算到这两个加数的最后一位,所以当i = -1的时候就退出循环,每一次计算完成以后就要计算前一位,所以i递减(即i--)

先问大家一个问题:int('0')和int 0有什么区别?

'0'是一个字符,可以理解成整数:48,每一个字符都会有它们对应的整数,称为ACSII码(淡黄色背景为控制字符,白色背景为可显示字符):

ASCII码一览表

二进制十进制十六进制字符/缩写解释
00000000000NUL (NULL)空字符
00000001101SOH (Start Of Headling)标题开始
00000010202STX (Start Of Text)正文开始
00000011303ETX (End Of Text)正文结束
00000100404EOT (End Of Transmission)传输结束
00000101505ENQ (Enquiry)请求
00000110606ACK (Acknowledge)回应/响应/收到通知
00000111707BEL (Bell)响铃
00001000808BS (Backspace)退格
00001001909HT (Horizontal Tab)水平制表符
00001010100ALF/NL(Line Feed/New Line)换行键
00001011110BVT (Vertical Tab)垂直制表符
00001100120CFF/NP (Form Feed/New Page)换页键
00001101130DCR (Carriage Return)回车键
00001110140ESO (Shift Out)不用切换
00001111150FSI (Shift In)启用切换
000100001610DLE (Data Link Escape)数据链路转义
000100011711DC1/XON
(Device Control 1/Transmission On)
设备控制1/传输开始
000100101812DC2 (Device Control 2)设备控制2
000100111913DC3/XOFF
(Device Control 3/Transmission Off)
设备控制3/传输中断
000101002014DC4 (Device Control 4)设备控制4
000101012115NAK (Negative Acknowledge)无响应/非正常响应/拒绝接收
000101102216SYN (Synchronous Idle)同步空闲
000101112317ETB (End of Transmission Block)传输块结束/块传输终止
000110002418CAN (Cancel)取消
000110012519EM (End of Medium)已到介质末端/介质存储已满/介质中断
00011010261ASUB (Substitute)替补/替换
00011011271BESC (Escape)逃离/取消
00011100281CFS (File Separator)文件分割符
00011101291DGS (Group Separator)组分隔符/分组符
00011110301ERS (Record Separator)记录分离符
00011111311FUS (Unit Separator)单元分隔符
001000003220(Space)空格
001000013321!
001000103422"
001000113523#
001001003624$
001001013725%
001001103826&
001001113927'
001010004028(
001010014129)
00101010422A*
00101011432B+
00101100442C,
00101101452D-
00101110462E.
00101111472F/
0011000048300
0011000149311
0011001050322
0011001151333
0011010052344
0011010153355
0011011054366
0011011155377
0011100056388
0011100157399
00111010583A:
00111011593B;
00111100603C<
00111101613D=
00111110623E>
00111111633F?
010000006440@
010000016541A
010000106642B
010000116743C
010001006844D
010001016945E
010001107046F
010001117147G
010010007248H
010010017349I
01001010744AJ
01001011754BK
01001100764CL
01001101774DM
01001110784EN
01001111794FO
010100008050P
010100018151Q
010100108252R
010100118353S
010101008454T
010101018555U
010101108656V
010101118757W
010110008858X
010110018959Y
01011010905AZ
01011011915B[
01011100925C\
01011101935D]
01011110945E^
01011111955F_
011000009660`
011000019761a
011000109862b
011000119963c
0110010010064d
0110010110165e
0110011010266f
0110011110367g
0110100010468h
0110100110569i
011010101066Aj
011010111076Bk
011011001086Cl
011011011096Dm
011011101106En
011011111116Fo
0111000011270p
0111000111371q
0111001011472r
0111001111573s
0111010011674t
0111010111775u
0111011011876v
0111011111977w
0111100012078x
0111100112179y
011110101227Az
011110111237B{
011111001247C|
011111011257D}
011111101267E~
011111111277FDEL (Delete)删除

继续回到循环,用两个加数的最后一位进行相加,得到的结果赋值给num。但是这里有一个地方要注意,我们创建的数组是字符类型,把字符转换成数字就是它的ASCII码,但0的ASCII码不是0,是48,所以在获取最后一位的时候要减去48(也可以写成-'0'):

 num = int(one[i]) - 48 + int(two[lentwo - j]) - 48 + a;

之后判断num是不是大于9,因为如果大于9,就需要进位。如果需要进位,那么让num-10,也就是只保留个位,并让a=1,这里a的作用是判断是否要进位,所以如果仔细看到话,在给num赋值时,最后加上了a;如果不需要进位,那么a=0,num不变。

既然算完了,那么就要把结果储存起来,在预处理之后,k=lentwo-1,也就是f数组最后一位的下标数,把我们计算的结果填在f数组的最后,k递减。b的作用会在输出时介绍。

k=lentwo;
    for (int i=b;i<k;i++){
        cout << f[i];
    }

现在f数组储存的结果就是代码计算的结果了,我们先把lenone或lentwo赋值给k,因为在循环中k被递减,最后为0,所以需要重新赋值。下面要一个循环来输出。b的作用是在循环的最后一遍检测它是不是0。如果不是0(也就是第二位要进位,预留出的0被改成了1),那么b=0,从f数组的第一位开始输出;如果是0(也就是第二位没有进位,预留出的0没有进行改动),那么b=1,从f数组的第一位开始输出,因为第一位是0,会影响美观。

至此,C++大整数加法的代码就分享完了,后续还会分享其他大整数运算的代码,敬请期待。

  • 19
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 大整数加法和乘法是计算机科学中常见的问题。大整数通常比机器原生数据类型表示的整数要大得多,因此需要采用特殊的算法来进行计算。 首先,我们来实现大整数加法。假设我们有两个大整数num1和num2,我们需要从最低位开始逐位相加,并且记录进位。具体的步骤如下: 1. 定义两个指针i和j分别指向num1和num2的最低位。 2. 初始化进位carry为0,并创建一个空的数组result用来存放结果。 3. 进行循环,直到指针i和j都越界: a. 将当前位的数字相加,加上进位carry,并将结果存放在sum变量中。 b. 将sum对10取余的结果添加到result数组中。 c. 更新进位carry为sum除以10的结果。 d. 更新指针i和j分别为下一位。 4. 如果carry不为0,将其添加到result数组的最高位。 这样就完成了大整数加法。 接下来,我们来实现大整数的乘法。同样地,我们需要从最低位开始逐位相乘,并且记录进位。具体的步骤如下: 1. 定义两个指针i和j分别指向num1和num2的最低位。 2. 初始化进位carry为0,并创建一个空的数组result用来存放结果。 3. 进行嵌套循环,外层循环遍历num1的每一位,内层循环遍历num2的每一位: a. 将当前位的数字相乘,加上进位carry,并将结果存放在product变量中。 b. 将product对10取余的结果添加到result数组中的对应位置。 c. 更新进位carry为product除以10的结果。 d. 更新指针j为下一位。 e. 将进位carry添加到result数组的下一个位置。 f. 更新指针i为下一位,重置指针j为num2的最低位。 4. 如果carry不为0,将其添加到result数组的最高位。 这样就完成了大整数的乘法。 总结起来,大整数加法和乘法都可以通过从最低位开始逐位相加或相乘,并记录进位来实现。需要注意的是,使用数组来存放结果,可以处理大整数不同位数的情况。 ### 回答2: 大整数加法和乘法的实现可以使用字符串来表示大整数,并按照进位运算的方法进行计算。 大整数加法的步骤如下: 1. 将两个大整数的字符串表示形式补齐到相同长度,可以在较短的字符串前面补0。 2. 从字符串的末尾(个位)开始遍历,将对应位置的数字相加。 3. 若相加的结果大于等于10,则需要进位。将进位的数字加到下一位的运算结果中。 4. 将每次相加的结果依次加入一个新的字符串中。 5. 如果最高位相加后有进位,则需要在最终结果的最前面加上进位。 大整数乘法的步骤如下: 1. 遍历两个大整数的字符串表示,将第一个数的每一位与第二个数的每一位相乘。 2. 通过一个二维数组来保存相乘的结果,其中每一行表示第一个数的一位与第二个数相乘的结果,乘积的每一位按照对应的位数存储。 3. 对于乘积的每一位,先计算当前位置上的乘积结果,然后将前一位(进位)加到当前位上。 4. 将每一位的结果依次加入一个新的字符串中。 5. 最后需要将每一位的结果按照进位的方式处理,直到最高位没有进位为止。 通过以上步骤,可以实现大整数加法和乘法的功能。这种方法适用于任意长度的大整数计算,无需考虑整数的大小限制。 ### 回答3: 要实现大整数加法和乘法,我们可以使用字符串来表示大整数,并模拟手工计算的过程进行运算。 对于加法,我们从个位开始按位相加,如果有进位则向前一位进位,直到所有位数相加完成,最后将结果拼接成新的字符串即可。 对于乘法,我们需要将每个位上的数字与另一个整数的每个位上的数字相乘,然后将结果按位相加,也就是说,我们从被乘数的个位开始,与乘数的每一位相乘,然后将结果保留到相应的位置。在进行下一位的计算时,需要将之前的结果整体往前进一位,因为每一位的值是乘数的某一位与当前被乘数位相乘的结果。最后将所有位的结果相加,得到最终的乘积。 需要注意的是,由于大整数可能会超过计算机能表示的范围,我们不能使用内置的整数类型进行运算,而要使用字符串来模拟整数的计算过程。在实现乘法时,还需要考虑到进位的情况。 总的来说,实现大整数加法和乘法需要注意好运算顺序和进位的处理,通过模拟手工计算的过程,可以得到正确的结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值