Вот эти побитовые сдвиги работли бы, если бы вы хранили число в двоичной системе счисления. Допустим, по 16 бит в каждом int. В таком виде вычисления побыстрее будут немного, но при выводе надо переводить число в 10-ую систему счисления. Судя по примеру ответа, вы храните по 3 десятичных знака в каждой ячейке. Т.е. у вас основание системы счисления 1000. И тут нужны сдвиги не битовые, а тысячные (которых не существует).
Вообще, основной цикл умножения должен быть примерно такой:
for (i = 0; i < len1; ++i)
for (j = 0; j < len2; ++j)
c[i+j] += a[i]*b[j];
И потом надо сделать все переносы. Вот тут и происходят сдвиг на i позиций (в системе счисления 1000) - это то самое
+i
в индексе у массива результата. И вместо выполнения прибавления, когда бит равен 1, тут происходит умножение на
a[i]
. В битовом случае оно как раз вырождается в умножение на 1 или 0 - прибавление или пропуск прибавления.
Это работает даже если вы в массивах a,b храните по несколько бит в каждой ячейке, или даже десятичных знаков. Это просто умножение в столбик в произвольной системе счисления.
Правда, тут проблема, что вот такое вот умножение, если вы храните по 32 бита, оно переполнится, и ответ надо в 64-битном типе получать. И даже если вы храните по 16 бит, то сумма может переполниться из-за большого количества слагаемых. Ну это решается выполнением переноса сразу же:
const int BASE = 1000; // База системы счисления. Оно же максимальное число в ячейке +1.
for (i = 0; i < len1; ++i) {
int carry = 0;
for (j = 0; j < len2; ++j) {
carry += c[i+j] + a[i]*b[j];
c[i+j] = carry % BASE;
carry /= BASE;
}
int i = len1+len2-1;
while (carry > 0) {
carry += c[i];
c[i] = carry % BASE;
carry /= BASE;
++i;
}
}