Алгоритм Карацубы для умножения полиномов

Я пытаюсь реализовать рекурсивный алгоритм Карацубы для умножения двух полиномов (одинаковой степени). Мой код все еще не работает для полиномов со степенью выше 1. Может ли кто-нибудь объяснить мне, что я делаю неправильно в своей функции? Он должен работать как для четных, так и для нечетных чисел коэффициентов.

Полиномы хранятся в массиве long, Каждый элемент представляет один коэффициент, поэтому 1 2 3 4 средства 1 + 2x + 3x^2 + 4x^3 и аргумент size это число коэффициентов.

long* karatsuba(const long *A, const long *B, int size) {
    long *lowA, *highA, *lowB, *highB, *midA, *midB;

    if (size == 1)
        return naive(A, B, size, size);

    int half = size / 2;

    lowA = new long[half];
    lowB = new long[half];
    midA = new long[half];
    midB = new long[half];
    highA = new long[half];
    highB = new long[half];

    // init low coefficients
    for(int i=0; i<half; i++){
        lowA[i] = A[i];
        lowB[i] = B[i];
    }

    // init high // init low coefficients
    for(int i=half; i<size; i++){
        highA[i-half] = A[i];
        highB[i-half] = B[i];
    }

    // init mid // init low coefficients
    for(int i=0; i<half; i++){
        midA[i] = lowA[i] + highA[i];
        midB[i] = lowB[i] + highB[i];
    }

    long *z0 = karatsuba(lowA, lowB, half);
    long *z1 = karatsuba(midA, midB, half);
    long *z2 = karatsuba(highA, highB, half);

    // compute the result
    long *result = new long[2*size-1];
    for(int i=0; i<half; i++){
        result[i + 2*half] = z2[i];
        result[i + half] = z1[i] - z0[i] - z2[i];
        result[i] = z0[i];
    }
    return result;
}

Моя главная проблема в том, что эта функция не вычисляет правильные результаты.

1 ответ

Я заметил полтора вопроса о правильности:

  1. индекс в "комбинированном цикле" ограничен длиной параметра рекурсивных вызовов вместо длины результата (почти вдвое больше длины параметра)
  2. Когда лимит правильный, промежуточные результаты "перекрываются", что требует накопления вместо присвоения.

Я никогда не использовал "современный C++" "в гневе" - если это работает, но оставляет вас недовольным кодом, подумайте о том, чтобы опубликовать свои замечания на Code Review.

Другие вопросы по тегам