C语言——数组形式的整数加法

一、题目简述

给定一个数组和整数,进行相加保存到数组中。
例如:
num=[1,2,0,0]代表1200
k=15
相加后 newnum=[1,2,1,5]

二、题目分析

如果将num数组化为整数,那么将有可能出现超出int范围的情况;所以采用将整数k进行拆分,与数组每一位对应相加的方法。
所以可以采用malloc一个新的数组(Array)来进行储存,但数组的长度如何来确定?
很显然,两个整数相加,最总结果只会等于最长整数位数或者比最长整数位数多一位。那么我们可以计算出k的位数,num的长度,比较它们取最大lenth,开辟lenth+1的数组长度,来保证Array能够保存所有位数。
但是我们并不知道相加完的两个数到底是lenth位数,还是lenth+1的位数,在将数存进Array中时,我们如果从后向前存储,便无法确定最后的位置。
例如:
num=[9, 9 ,5]
k=58;
num+k=995+58=1053;
Array=[1,0,5,3]
但是在两数相加完成前,我们并不知道Array是从2下标位置开始存,还是3下标位置。所有我们可以采用倒着存储的方式。
Array=[3,5,0,1]
这样只需在结束后逆置一下数组即可。

三、代码分析

   while(tmp)
   {
     tmp/=10;
     Ksize++;//计算数字k的位数
   }
   int lenth=(numSize>Ksize)?(numSize):(Ksize);
   int* Array=(int*)malloc(sizeof(int)*(lenth+1));//开辟一个新的数组
1、开辟新数组

计算k的位数,将最大值赋给lenth。malloc一个新数组Array,长度为lenth+1。

   int Arraypos=0;//num数组开始位置
   int numpos=numSize-1;//num数组末尾位置
   int carry=0;//进位标志
   while(lenth--)
   {
    int a;
    if(numpos<0)
    a=0;//数组长度比k位数小
    else
    a=num[numpos];
    Array[Arraypos]=k%10+a+carry;//将每一位的数逆序存入新数组
    k/=10;
     if(Array[Arraypos]>9)
     {
        Array[Arraypos]-=10;
        carry=1;
     }
     else
     carry=0;
     Arraypos++;
     numpos--;
   }
2、判断是否越界

Arraypos是Array的下标位置,开始为0;numpos为数组num开始位置,开始为numSize-1(num数组末尾)。a用来保存num[numpos]的值;carry表示是否进位,开始置为0,表示无进位。
在相加之前,要对numpos的位置进行判断,因为会出现num长度小于k位数的情况,那么在进行相加,numpos就会越界。
例如:
在这里插入图片描述
当加法还没有完成时,numpos已经走到0的位置,执行numpos–后便会造成越界访问。所有对numpos的值进行一个判断:numpos小于0时a置零即可。

    if(numpos<0)
    a=0;//数组长度比k位数小
    else
    a=num[numpos];
3、按位相加,保存到Array

将num的每一项与k每一位相加,执行:Array[Arraypos]=k%10+a+carry。
保存到Array[Arraypos]中。
对Array[Arraypos]进行判断,若Array[Arraypos]>9则说明需要进位,carry置为1;否则carry置为0。
直到所有位数相加完成,循环结束。

4、处理最后一位

若num=[1,2,0,0]
k=15
那么Array=[5,1,2,1,],Arraypos的值则为数组长度。
若num=[9,9,5]
k=58
在相加结束后
Array=[3,5,0, ],carry=1
说明仍有一位进位未处理,若carry=1,将Array[Arraypos]置1,Arrypos++即可。

   if(carry==1)//循环结束carry仍为1,还有一个进位未处理
   {
    Array[Arraypos]=1;
    Arraypos++;
   }
5、逆置数组

将Array数组进行逆置

   int left=0;
   int right=Arraypos-1;
   while(left<right)//将数组逆置
   {
    int tmp=Array[left];
    Array[left]=Array[right];
    Array[right]=tmp;
    left++;
    right--;
   }

四、完整代码

   int* addToArrayForm(int* num, int numSize, int k, int* returnSize) {
   int Ksize=0;
   int tmp=k;
   while(tmp)
   {
     tmp/=10;
     Ksize++;//计算数字k的位数
   }
   int lenth=(numSize>Ksize)?(numSize):(Ksize);
   int* Array=(int*)malloc(sizeof(int)*(lenth+1));//开辟一个新的数组
   int Arraypos=0;//num数组开始位置
   int numpos=numSize-1;//num数组末尾位置
   int carry=0;//进位标志
   while(lenth--)
   {
    int a;
    if(numpos<0)
    a=0;//数组长度比k位数小
    else
    a=num[numpos];
    Array[Arraypos]=k%10+a+carry;//将每一位的数逆序存入新数组
    k/=10;
     if(Array[Arraypos]>9)
     {
        Array[Arraypos]-=10;
        carry=1;
     }
     else
     carry=0;
     Arraypos++;
     numpos--;
   }
   if(carry==1)//循环结束carry仍为1,还有一个进位未处理
   {
    Array[Arraypos]=1;
    Arraypos++;
   }
   int left=0;
   int right=Arraypos-1;
   while(left<right)//将数组逆置
   {
    int tmp=Array[left];
    Array[left]=Array[right];
    Array[right]=tmp;
    left++;
    right--;
   }
   *returnSize=Arraypos;
    return Array;//返回新数组
}
  • 50
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值