提问人:Richard Bryan 提问时间:9/27/2023 最后编辑:chqrlieRichard Bryan 更新时间:9/28/2023 访问量:155
计算一个非常大的整数
Calculating a very large integer
问:
如何添加两个大整数,我尝试过使用数组,但它仍然有一些错误。 例如:一个 23 位 + 25 位正整数 (2345235... + 34634235....)
我尝试过使用数组来分隔数字并最终将它们相加,但是仍然存在一些错误,例如何时,它将输出,或者当它是24位数字+ 25位数字时,代码变得复杂。有什么简单的方法可以做到这一点吗?999 + 999
998
#include <stdio.h>
int main(void)
{
int length_A, length_B, times;
long long int A[101] = {0};
long long int B[101] = {0};
long long int total[101] = {0};
scanf("%d", &length_A);
for (int i = 0; i < length_A; i++)
{
scanf("%1lld", &A[i]);
}
scanf("%d", &length_B);
for (int j = 0; j < length_B; j++)
{
scanf("%1lld", &B[j]);
}
if (length_A > length_B)
{
times = length_A - length_B;
for (int l = 0; l < times; l++)
{
total[l] = A[l];
}
for (int k = 0; k < length_B; k++)
{
total[k+times] = A[k+times] + B[k];
if(total[k+times] > 9)
{
if (total[k+times-1] == 9)
{
total[k+times-2]++;
total[k+times-1] = 0;
total[k+times] -= 10;
}
else if (total[k+times-1] < 9)
{
total[k+times-1]++;
total[k] -= 10;
}
}
}
for (int z = 0; z < length_B; z++)
{
printf("%lld", total[z]);
}
}
else if (length_B > length_A)
{
times = length_B - length_A;
for (int k = 0; k < length_B; k++)
{
for (int l = 0; l < times; l++)
{
total[l] = B[l];
}
total[k+times] = A[k] + B[k+times];
if(total[k] > 9)
{
if (total[k-times] == 9)
{
total[k-times-1]++;
total[k-times] = 0;
total[k] -= 10;
}
else
{
total[k-1]++;
total[k] -= 10;
}
}
}
for (int z = 0; z < length_B; z++)
{
printf("%lld", total[z]);
}
}
else
{
for (int k = 0; k < length_B; k++)
{
total[k] = A[k] + B[k];
if(total[k] > 9)
{
if (total[k-1] == 9)
{
total[k-2]++;
total[k-1] = 0;
total[k] -= 10;
}
else
{
total[k-1]++;
total[k] -= 10;
}
}
}
for (int z = 0; z < length_B; z++)
{
printf("%lld", total[z]);
}
}
}
答:
0赞
chux - Reinstate Monica
9/27/2023
#1
- OP 的代码从最重要到最不重要。从最不重要(最高指数)到最重要添加更容易和更常见,同时跟踪进位。
// General algorithm. Needs more work to handle if the lengths of a, b differ.
carry = 0;
for (index = least; index >= most; index--) {
sum = a[index] + b[index] + carry;
total[index] = sum %10;
carry = sum / 10;
}
- OP 的代码不处理 2 个数字的总和是否构成最高有效数字的进位。事实上,它试图设置 .
total[-1] = ...
// After the above loop
if (carry) {
// Shift sum digits "right"
// Then set the new most significant digit.
}
数组应比 长 1,以处理潜在的最后“进位”。
total
A
B
long long int A[101] = {0};
是过分的。 足以保存所有 1 位和 2 位十进制数字值。signed char A[101] = {0};
有什么简单的方法可以做到这一点吗?
也许,对某些人来说很容易,对学习者来说是一个挑战。
一个关键的策略是分而治之。
考虑将输入与加法和输出分开。
Form 3 函数。
// Return length
int big_number_read(int max_length, signed char *destination);
// Return length
int big_number_add(int max_sum_length, signed char *sum,
int a_length, signed char *a,
int b_length, signed char *b);
void big_number_print(int a_length, signed char *a);
然后形成main()
#define BIGINT_LEN_MAX 100
int main() {
signed char a[BIGINT_LEN_MAX];
signed char b[BIGINT_LEN_MAX];
signed char sum[BIGINT_LEN_MAX + 1];
int length_a = big_number_read(BIGINT_LEN_MAX, a);
int length_b = big_number_read(BIGINT_LEN_MAX, b);
int length_sum = big_number_add(BIGINT_LEN_MAX + 1, sum,
length_a, a, length_b, b);
big_number_print(length_sum, sum);
}
0赞
chqrlie
9/28/2023
#2
计算大型加法的方法存在问题:
- 您应该计算从最低有效数字到最高有效数字的数字,像使用高中算术一样传播进位。
- 如果总和产生的数字大于 和 ,则应为额外的数字腾出空间。
A
B
- 您应该使用较小的类型来保存数字:对于 to 的范围内的值来说是矫枉过正的。您甚至可以直接使用数字的字符表示。
long long int
0
9
下面是代码的修改版本:
#include <stdio.h>
int main(void) {
int length_A, length_B, length_total, i, j, k, carry;
int A[101], B[101], total[101];
if (scanf("%d", &length_A) != 1 || length_A <= 0 || length_A > 100)
return 1;
for (i = 0; i < length_A; i++) {
if (scanf("%1d", &A[i]) != 1)
return 1;
}
if (scanf("%d", &length_B) != 1 || length_B <= 0 || length_B > 100)
return 1;
for (i = 0; i < length_B; i++) {
if (scanf("%1d", &B[i]) != 1)
return 1;
}
length_total = (length_A > length_B) ? length_A + 1 : length_B + 1;
carry = 0;
i = length_A;
j = length_B;
k = length_total;
while (i > 0 && j > 0) {
int digit = A[--i] + B[--j] + carry;
carry = (digit > 9);
digit -= carry * 10;
total[--k] = digit;
}
while (i > 0) {
int digit = A[--i] + carry;
carry = (digit > 9);
digit -= carry * 10;
total[--k] = digit;
}
while (j > 0) {
int digit = B[--j] + carry;
carry = (digit > 9);
digit -= carry * 10;
total[--k] = digit;
}
if (carry) {
total[--k] = carry;
}
while (k < length_total) {
printf("%d", total[k++]);
}
printf("\n");
return 0;
}
下面是一种替代方法,它将数字读取为没有长度前缀的字符串并直接使用字符串:
#include <stdio.h>
#include <string.h>
int main(void) {
char A[101], B[101], total[102];
if (scanf(" %100[0-9] %100[0-9]", A, B) != 2)
return 1;
int length_A = strlen(A);
int length_B = strlen(B);
int length_total = (length_A > length_B) ? length_A + 1 : length_B + 1;
int i = length_A;
int j = length_B;
int k = length_total;
int carry = 0;
total[k] = '\0';
while (i > 0 && j > 0) {
int digit = A[--i] + B[--j] + carry - '0';
carry = (digit > '9');
digit -= carry * 10;
total[--k] = (char)digit;
}
while (i > 0) {
int digit = A[--i] + carry;
carry = (digit > '9');
digit -= carry * 10;
total[--k] = (char)digit;
}
while (j > 0) {
int digit = B[--j] + carry;
carry = (digit > '9');
digit -= carry * 10;
total[--k] = (char)digit;
}
if (carry) {
total[--k] = (char)(carry + '0');
}
printf("%s\n", total + k);
return 0;
}
评论
scanf
A
B
char