首先是字符串翻转函数,大数相加、相减和相乘中都用到了这个函数
/*
** 字符串翻转
*/
void Reverse(char *str, int n)
{
int i;
for (i = 0; i < n / 2; i++)
{
char tmp;
tmp = str[i];
str[i] = str[n-i-1];
str[n-i-1] = tmp;
}
}
1.大数相加
/*
** 这里假设str1和str2表示的数为非负数
*/
void BigNumAdd(char *str1, char *str2, char *result)
{
if (str1 == NULL || str2 == NULL || result == NULL)
{
return;
}
int len1, len2;
len1 = strlen(str1);
len2 = strlen(str2);
Reverse(str1, len1); // 将str1翻转
Reverse(str2, len2); // 将str2翻转
int weight = 0; // 表示进位
int sum = 0;
int index = 0; // 表示result的下标,从0开始,相加结束后应翻转
int i, j;
i = 0; // 表示str1的下标
j = 0; // 表示str2的下标
while (i < len1 && j < len2) // 两个数对应的每一位进行相加
{
sum = str1[i] - '0' + str2[j] - '0' + weight;
weight = sum / 10; // 计算是否要进位
sum %= 10;
result[index++] = sum + '0';
i++;
j++;
}
while (i < len1) // str2已经加完了,这时还要考虑str1和str2的最高位相加时是否有进位的情况
{
sum = str1[i] - '0' + weight;
weight = sum / 10;
sum %= 10;
result[index++] = sum + '0';
i++;
}
while (j < len2) // str1已经加完了,这时还要考虑str1和str2的最高位相加时是否有进位的情况
{
sum = str2[j] - '0' + weight;
weight = sum / 10;
sum %= 10;
result[index++] = sum + '0';
j++;
}
if (weight > 0) // str1和str2都已经加完了,这时还要考虑最后一步中是否产生了进位
{
result[index++] = weight + '0';
}
result[index] = '\0';
Reverse(result, index); // 对result进行翻转,得到最终的结果
}
2.大数相减
/*
** 这里假设str1和str2表示的数为非负数,并且str1表示的数大于等于str2的数
*/
void BigNumMinus(char *str1, char *str2, char *result)
{
if (str1 == NULL || str2 == NULL || result == NULL)
{
return;
}
int len1, len2;
len1 = strlen(str1);
len2 = strlen(str2);
Reverse(str1, len1); // 将str1翻转
Reverse(str2, len2); // 将str2翻转
int index = 0; // 表示result的下标,从0开始,相减结束后应翻转
int i, j;
i = 0; // 表示str1的下标
j = 0; // 表示str2的下标
while (i < len1 && j < len2) // 两个数对应的每一位进行相减
{
result[index] = (str1[i] - '0') - (str2[j] - '0');
if (result[index] < 0) // 当str1对应的位小于str2对应的位,应借位
{
result[index] = result[index] + 10 + '0';
str1[i+1] = str1[i+1] - 1;
}
else
{
result[index] = result[index] + '0';
}
index++;
i++;
j++;
}
while (i < len1) // str2已减完,但是可能存在借位的情况
{
result[index] = str1[i] - '0';
if (result[index] < 0)
{
result[index] = result[index] + 10 + '0';
str1[i+1] = str1[i+1] - 1;
}
else
{
result[index] = result[index] + '0';
}
index++;
i++;
}
while (result[--index] == '0') // 去掉result后面的'0' 如40000 - 39999时会存在一些多源的'0'字符
;
result[++index] = '\0';
Reverse(result, index); // 对result进行翻转,得到最终的结果
}
3.大数相乘
/*
** 这里假设str1和str2表示的数为非负数,并且str1表示的数大于等于str2的数
*/
void BigNumMulti(char *str1, char *str2, char *result)
{
if (str1 == NULL || str2 == NULL || result == NULL)
{
return;
}
if (strcmp(str1, "0") == 0 || strcmp(str2, "0") == 0)
{
strcpy(result, "0");
return;
}
int len1, len2;
len1 = strlen(str1);
len2 = strlen(str2);
Reverse(str1, len1); // 将str1翻转
Reverse(str2, len2); // 将str2翻转
memset(result, '0', N);
int i, j;
int multiFlag; // 乘积进位
int addFlag; // 加法进位
for (i = 0; i < len2; i++) // str2的每一位
{
multiFlag = 0;
addFlag = 0;
for (j = 0; j < len1; j++) // str1的每一位
{
int temp1 = (str2[i] - '0') * (str1[j] - '0') + multiFlag;
multiFlag = temp1 / 10;
temp1 = temp1 % 10;
int temp2 = (result[i+j] - '0') + temp1 + addFlag;
addFlag = temp2 / 10;
result[i+j] = temp2 % 10 + '0';
}
result[i + len1] += multiFlag + addFlag;
}
if (result[len1+len2-1] == '0')
{
result[len1+len2-1] = '\0';
}
else
{
result[len1+len2] = '\0';
}
Reverse(result, strlen(result)); // 对result进行翻转,得到最终的结果
}