Длинное умножение
Во входном файле задано два целых положительных числа, одно в первой строке, второе — во второй строке. Нужно вычислить произведение этих двух чисел и вывести его в выходной файл. Количество десятичных цифр в каждом входном числе может достигать 1 000. Поэтому требуется реализовать умножение двух длинных чисел “столбиком”. Моя программа работает правильно, но система тестирования не хочет ее принимать. Подскажите, почему, и как это можно исправить?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define BASE 1000000000u
#define WIDTH 9
typedef uint32_t Digit;
typedef uint64_t Digit2;
#define SCN_DIGIT SCNu32
#define PRI_DIGIT PRIu32
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
Digit *multiply(Digit p[], size_t n_p,
const Digit a[], size_t n_a,
const Digit b[], size_t n_b)
{
for (; n_a > 0 && a[n_a - 1] == 0; --n_a);
for (; n_b > 0 && b[n_b - 1] == 0; --n_b);
if (n_a + n_b > n_p)
return NULL;
memset(p, 0, n_p * sizeof *p);
for (size_t i_b = 0; i_b < n_b; ++i_b)
{
Digit carry = 0;
for (size_t i_a = 0; i_a < n_a; ++i_a)
{
Digit2 digit = p[i_a + i_b] + (Digit2) a[i_a] * b[i_b] + carry;
p[i_a + i_b] = digit % BASE;
carry = digit / BASE;
}
p[n_a + i_b] += carry;
}
return p;
}
Digit *from_string(Digit a[], size_t n_a, const char *str)
{
size_t i_a = 0;
const char *pstr = str + strlen(str);
char format[16];
sprintf(format, "%%%d" SCN_DIGIT, WIDTH);
for(; pstr - str > WIDTH && i_a < n_a; ++i_a)
sscanf(pstr -= WIDTH, format, &a[i_a]);
if (i_a == n_a)
return NULL;
sprintf(format, "%%%td" SCN_DIGIT, pstr - str);
sscanf(str, format, &a[i_a]);
++i_a;
memset(a + i_a, 0, (n_a - i_a) * sizeof *a);
return a;
}
char *to_string(char *str, size_t n_str, Digit a[], size_t n_a)
{
for (; n_a > 0 && a[n_a - 1] == 0; --n_a);
size_t i_a = n_a - 1;
char *pstr = str;
char format[16] = "%" PRI_DIGIT;
int n_chars = snprintf(NULL, 0, format, a[i_a]);
if (n_chars + 1 > n_str)
return NULL;
sprintf(pstr, format, a[i_a]);
pstr += n_chars;
n_str -= n_chars;
sprintf(format, "%%0%d" PRI_DIGIT, WIDTH);
while (i_a-- > 0)
{
if (WIDTH + 1 > n_str)
return NULL;
sprintf(pstr, format, a[i_a]);
pstr += WIDTH;
n_str -= WIDTH;
}
return str;
}
int main(void)
{
char buffer[1024];
scanf("%s", buffer);
Digit a[10];
from_string(a, ARRAY_SIZE(a), buffer);
scanf("%s", buffer);
Digit b[10];
from_string(b, ARRAY_SIZE(b), buffer);
Digit p[ARRAY_SIZE(a) + ARRAY_SIZE(b)];
multiply(p, ARRAY_SIZE(p), a, ARRAY_SIZE(a), b, ARRAY_SIZE(b));
to_string(buffer, ARRAY_SIZE(buffer), p, ARRAY_SIZE(p));
printf("%s\n", buffer);
}