大数运算之大数相减

来源:互联网 发布:软件产品设计流程 编辑:程序博客网 时间:2024/06/04 19:18
大数减法运算

第一次在CSDN写博客,督促自己不断学习、巩固和进步,希望能和大家一起成长~

在编程实现整数运算时,作为程序猿/媛,我们知道计算机中的int、long或者long long的所占的内存空间是有限的,当整数超过一定大小,这些类型就无法表示整数的值,否则数据会被“截断”,无法得到正确的结果。
那么,该如何实现大数运算呢?刚开始我也是如此的疑惑,但稍加思索,你很快可以想到最简单的方法——使用int数组(或者char数组,既满足要求,又可节省空间)来进行运算。假设有两个大数,char *s1 = "4543636436274354646", char *s2 = "456360989", 我们可以取出每一位的值,放到int数组。

值得注意的是,char *中低地址存放的是高位的数字字符,而运算中我们需要将低位对齐,所以首先将字符串的字符逆序存入数组中, 个位数是数组第一个元素:

int idx, len1, len2, *array1, *array2;
len1 = strlen(s1);
array1 = (int *)calloc(len1, sizeof(int));
for (idx = 0; idx < len1; idx++){
array1[idx] = s1[len1 - 1 - idx] - '0';
}

照此将s2的数字存到array2中,简单起见,这里假设array1表示的数字大于等于array2表示的数值。接着就是按照减法的定义,被减数当前位小于减数,则向高位借1,自身加10,逻辑如下:
for (idx = 0; idx < len2; idx++) {
if (array1[idx] < array2[idx]) {
array1[idx+1]--;
array1[idx] += 10;
}

array1[idx] -= array2[idx];
}

运算结束后,需要将结果以字符串形式返回。这里有一点很容易被忽略,数组中最高位的0需要清除,不显示到结果的字符串中。
方法同样很简单,从array1最大的元素开始遍历,直到第一个不为0的数字,该位置及之前的数组元素即为运算结果。
最后,还需注意将数组的元素值 + ‘0’,并逆序写到字符串中,注意将字符串存储结果后的一位赋值'\0',表示结束,得到正确的结果。完整代码如下:


/**
* the value of s1 is larger than s2
*/
char *sub(const char *s1, const char *s2)
{
char *result = NULL;
int *array1, *array2;
int len1, len2, idx, retLen;

if (NULL == s1 || NULL == s2) {
printf("input error, cannot be null\n");
return NULL;
}

len1 = strlen(s1);
len2 = strlen(s2);
if (0 == len1 || 0 == len2) {
printf("input string length cannot be 0\n");
return NULL;
}

array1 = (int *)calloc(len1, sizeof(int));
if (NULL == array1) {
printf("calloc error:%s\n", strerror(errno));
return NULL;
}

array2 = (int *)calloc(len2, sizeof(int));
if (NULL == array2) {
printf("calloc error:%s\n", strerror(errno));
free(array1);
return NULL;
}

result = (char *)calloc(len1+1, sizeof(char));
if (NULL == result) {
printf("calloc error:%s\n", strerror(errno));
free(array1);
free(array2);
return NULL;
}

for (idx = 0; idx < len1; idx++) {
array1[idx] = s1[len1-idx-1] - '0';
}

for (idx = 0; idx < len2; idx++) {
array2[idx] = s2[len2-idx-1] - '0';
}

for (idx = 0; idx < len2; idx++) {
if (array1[idx] < array2[idx]) {
array1[idx+1]--;
array1[idx] += 10;
}

array1[idx] -= array2[idx];
}

retLen = len1 - 1;
for (idx = len1-1; idx >= 0; idx--) {
if (retLen == idx && array1[idx] == 0) {
retLen--;
} else {
break;
}
}

retLen = (retLen < 0) ? 0 : retLen;
for (idx = retLen; idx >= 0; idx--) {
result[retLen-idx] = array1[idx] + '0';
}

result[retLen+1] = '\0';
free(array1);
free(array2);
return result;
}