练习题——大数加法

大数指位数超长的数,以至于使用int(32,64)等C++语言内置数据类型已经不足以涵盖。

这里实现1000位的大数加法。

 

思路为将数保存成字符数组/字符串形式,按位模拟手工计算时的加法,

主要步骤为:

1)获取原数和加数的位数

 

2)如果位数相同不做处理,位数不同,则需要将小的数前补0对齐到大的数

(如 101 + 99,需要将99前补0对齐到101,

变成101+ 099)

 

3)从后至前,从左至右,按位相加处理进位

 

4)若最左边发生了进位,则视为溢出的情况,此时需要将结果整体右移一位,在左边补‘1’

 

代码实现:

  测试代码:

//数组最大长度
const int MAX_LENGTH = 1000;
//原数数组
char *primitiveStr = new char[MAX_LENGTH + 1]{};
//加数数组
char *addStr = new char[MAX_LENGTH + 1]{};
//结果数组
char *resultStr = new char[MAX_LENGTH + 1]{};
//原数长度
int primitiveLength = 0;
//加数长度
int addLength = 0;

//输入原数和加数
std::cin >> primitiveStr;
std::cin >> addStr;

//获取原数和加数数位
getLength(primitiveStr, addStr, &primitiveLength, &addLength);
//按照数位差对齐
align(primitiveStr, addStr, primitiveLength, addLength);
//按位相加并处理进位和左溢出
add(primitiveStr, addStr, primitiveLength, addLength, resultStr);

//输出计算结果
std::cout << primitiveStr << " + " << addStr << " = " << resultStr << std::endl;

//清除堆内存
delete primitiveStr[];
delete addStr[];
delete resultStr[];
primitiveStr = nullptr;
addStr = nullptr;
resultStr = nullptr;

 

  获取原数和加数的数位的函数:

void getLength(char *pStr,char *aStr,int *pLength,int *aLength) {
    bool isNotEnd = true;
    int i = 0;
    while (isNotEnd) {
        //0也即'\0'
        if (pStr[i]!=0) {
            (*pLength)++;
        }
        if (aStr[i]!=0) {
            (*aLength)++;
        }
        if (pStr[i]==0&&aStr[i]==0) {
            isNotEnd = false;
        }
        i++;
    }
}

 

  对齐数位用到的函数:

void align(char *pStr,char *aStr,int pLength,int aLength) {
    int offset = pLength - aLength;
    //有位差且没逆序,将addStr对齐到primitiveStr
    if (offset>0) {
        //从末位开始,例如将101+99对齐到101+099
        for (int i = pLength,j = 0; i > offset; i--,j++) {
            *(aStr + i) = *(aStr + aLength - j);
        }
        //补‘0’操作
        for (int i = 0; i < offset;i++) {
            *(aStr + i) = '0';
        }
    }
    //有位差且逆序,将primitiveStr对齐到addStr
    if (offset<0) {
        for (int i = aLength, j = 0; i > -offset;i--,j++) {
            *(pStr + i) = *(pStr + pLength - j);
        }
        for (int i = 0; i < -offset;i++) {
            *(pStr + i) = '0';
        }
    }
}        

 

  按位相加,并处理进位以及左溢出

void add(char* pStr,char* aStr,int pLength,int aLength,char* rStr) {
    int rLength = pLength > aLength ? pLength : aLength;
    //进位
    int carry = 0;
    for (int i = rLength; i >= 0; i--) {
        //字符转数字
        int primitiveNum = (int)(*(pStr+i) - '0');
        int addNum = (int)(*(aStr+i) - '0');
        int resultNum = primitiveNum + addNum + carry;
        //转字符存入结果数组
        if (resultNum >= 10) {    //有进位
            carry = 1;
            *(rStr+i) = char((resultNum % 10) + '0');
        }
        else {    //无进位
            carry = 0;
            *(rStr + i) = char(resultNum + '0');
        }
    }
    //检查到上溢
    if (carry==1) {
        //整体右移
        for (int i = rLength; i > 0; i--) {
            *(rStr+i) = *(rStr+i - 1);
        }
        //左边补1
        *(rStr+0) = '1';
    }
    //用'\0'截断
    *(rStr + rLength + 1) = '\0';
}

 

posted on 2018-08-01 22:11  jyunlon  阅读(597)  评论(0编辑  收藏  举报

导航