如何对大数求和
How to sum big numbers
我正在尝试编写一个程序,它可以对非常大的数字求和。不幸的是我被卡住了——它没有 return 任何结果,即使我注释掉 malloc & realloc(编译器似乎失败了)。有任何想法吗?我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j,x;
char *actual = NULL;
char *sum = NULL;
void init () {
sum = malloc(500);
actual = malloc(500);
}
void calculate (char *argv[]) {
int rest = 0;
actual = *argv;
actual = realloc(actual, strlen(*argv));
if (strlen(actual) > strlen(sum)) {
sum = realloc(sum, strlen(actual) + 1);
} else sum = realloc(sum, strlen(sum) + 1);
long b;
for (b = 1; b < strlen(actual); b++) {
rest = rest + atoi(&sum[strlen(sum) - b]) + atoi(&actual[strlen(actual) - b]);
if (rest > 9) {
sum[strlen(sum) - b] = rest - 10;
rest = 1; // carrying over 1
} else {
sum[strlen(sum) - b] = rest;
rest = 0;
}
}
}
void writeResult () {
printf("VYPIS - sum:");
printf("strlen souctu je: %lu\n",strlen(sum));
long c;
for (c = 0; c <= strlen(sum); c++) {
printf("%c",sum[c]);
}
printf("\n");
}
void emtpy () {
free(actual);
free(sum);
}
int main(int argc, char * argv[]) {
init();
for (i = 1; i < argc; i++) {
calculate(&argv[i]);
}
writeResult();
emtpy();
return 0;
}
尝试 realloc
argv
是未定义的行为。通常,您不应该 realloc
没有 malloc
编辑或从显式将内存所有权转移给您的函数接收到的内容。
另请注意,atoi
需要一个以 null 结尾的 C 字符串,因此将长字符串的一部分传递给它是不正确的。如果你想得到一个 char
数字的数值,减去 '0'
,像这样:
int digit = actual[strlen(actual) - b] -'0';
要将单个十进制数字转换为 char
,请向后添加 '0'
:
res[b] = digit + '0';
你的代码太复杂了,有几个问题:
- 不能使用
atoi
将字符转换成值,可以这样很简单地完成:int value = c - '0'
.
- 您不应修改
argv
数组中的字符串。特别是你不能重新分配它们。这会调用未定义的行为。
- 始终为最终
'[=14=]'
分配或重新分配比您要存储在结果数组中的字符串的长度多 1 个字节,并记住设置最后一个字节。
- 您应该像手动计算一样从右到左计算加法,跟踪从一个数字到下一个数字的进位,可能会添加一个额外的前导数字。
这是针对您的问题的简化版,显示了如何处理以 10 为基数的大数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *bigsum(char *res, const char *arg) {
size_t pos1, pos2, pos3, len3;
unsigned int carry;
pos1 = strlen(res);
pos2 = strlen(arg);
len3 = pos3 = (pos1 < pos2) ? pos2 + 1 : pos1 + 1;
/* reallocate the result array to one more than the larger operand */
res = realloc(res, len3 + 1);
/* set the terminating '[=10=]' at the end of result */
res[pos3] = '[=10=]';
for (carry = 0; pos3 > 0; carry /= 10) {
if (pos1 > 0) carry += res[--pos1] - '0';
if (pos2 > 0) carry += arg[--pos2] - '0';
res[--pos3] = '0' + carry % 10;
}
while (res[0] == '0' && len3 > 1) {
/* normalize the result: remove redundant initial zeroes */
memmove(res, res + 1, len3--);
}
return res;
}
int main(int argc, const char **argv) {
/* initialize the result to "0" as an allocated string */
char *result = strcpy(malloc(2), "0");
int i;
for (i = 1; i < argc; i++) {
result = bigsum(result, argv[i]);
}
printf("%s\n", result);
return 0;
}
我正在尝试编写一个程序,它可以对非常大的数字求和。不幸的是我被卡住了——它没有 return 任何结果,即使我注释掉 malloc & realloc(编译器似乎失败了)。有任何想法吗?我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j,x;
char *actual = NULL;
char *sum = NULL;
void init () {
sum = malloc(500);
actual = malloc(500);
}
void calculate (char *argv[]) {
int rest = 0;
actual = *argv;
actual = realloc(actual, strlen(*argv));
if (strlen(actual) > strlen(sum)) {
sum = realloc(sum, strlen(actual) + 1);
} else sum = realloc(sum, strlen(sum) + 1);
long b;
for (b = 1; b < strlen(actual); b++) {
rest = rest + atoi(&sum[strlen(sum) - b]) + atoi(&actual[strlen(actual) - b]);
if (rest > 9) {
sum[strlen(sum) - b] = rest - 10;
rest = 1; // carrying over 1
} else {
sum[strlen(sum) - b] = rest;
rest = 0;
}
}
}
void writeResult () {
printf("VYPIS - sum:");
printf("strlen souctu je: %lu\n",strlen(sum));
long c;
for (c = 0; c <= strlen(sum); c++) {
printf("%c",sum[c]);
}
printf("\n");
}
void emtpy () {
free(actual);
free(sum);
}
int main(int argc, char * argv[]) {
init();
for (i = 1; i < argc; i++) {
calculate(&argv[i]);
}
writeResult();
emtpy();
return 0;
}
尝试 realloc
argv
是未定义的行为。通常,您不应该 realloc
没有 malloc
编辑或从显式将内存所有权转移给您的函数接收到的内容。
另请注意,atoi
需要一个以 null 结尾的 C 字符串,因此将长字符串的一部分传递给它是不正确的。如果你想得到一个 char
数字的数值,减去 '0'
,像这样:
int digit = actual[strlen(actual) - b] -'0';
要将单个十进制数字转换为 char
,请向后添加 '0'
:
res[b] = digit + '0';
你的代码太复杂了,有几个问题:
- 不能使用
atoi
将字符转换成值,可以这样很简单地完成:int value = c - '0'
. - 您不应修改
argv
数组中的字符串。特别是你不能重新分配它们。这会调用未定义的行为。 - 始终为最终
'[=14=]'
分配或重新分配比您要存储在结果数组中的字符串的长度多 1 个字节,并记住设置最后一个字节。 - 您应该像手动计算一样从右到左计算加法,跟踪从一个数字到下一个数字的进位,可能会添加一个额外的前导数字。
这是针对您的问题的简化版,显示了如何处理以 10 为基数的大数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *bigsum(char *res, const char *arg) {
size_t pos1, pos2, pos3, len3;
unsigned int carry;
pos1 = strlen(res);
pos2 = strlen(arg);
len3 = pos3 = (pos1 < pos2) ? pos2 + 1 : pos1 + 1;
/* reallocate the result array to one more than the larger operand */
res = realloc(res, len3 + 1);
/* set the terminating '[=10=]' at the end of result */
res[pos3] = '[=10=]';
for (carry = 0; pos3 > 0; carry /= 10) {
if (pos1 > 0) carry += res[--pos1] - '0';
if (pos2 > 0) carry += arg[--pos2] - '0';
res[--pos3] = '0' + carry % 10;
}
while (res[0] == '0' && len3 > 1) {
/* normalize the result: remove redundant initial zeroes */
memmove(res, res + 1, len3--);
}
return res;
}
int main(int argc, const char **argv) {
/* initialize the result to "0" as an allocated string */
char *result = strcpy(malloc(2), "0");
int i;
for (i = 1; i < argc; i++) {
result = bigsum(result, argv[i]);
}
printf("%s\n", result);
return 0;
}