Я реализовал алгоритм умножения Карацубы для моих образовательных целей. Теперь я ищу дальнейшие улучшения. Я реализовал какую-то длинную арифметику и хорошо работает, не использую ли я базу целочисленного представления более . с базой и компиляции с clang++ -O3
умножения двух случайных чисел в диапазоне [10^50000, 10^50001]
принимает:Усовершенствование умножения Карацубы
Naive algorithm took me 1967 cycles (1.967 seconds)
Karatsuba algorithm took me 400 cycles (0.4 seconds)
И те же номера с базой :
Naive algorithm took me 409 cycles (0.409 seconds)
Karatsuba algorithm took me 140 cycles (0.14 seconds)
Есть ли способ для улучшения это результаты? Теперь я использую такую функцию, чтобы завершить мой результат:
void finalize(vector<int>& res) {
for (int i = 0; i < res.size(); ++i) {
res[i + 1] += res[i]/base;
res[i] %= base;
}
}
Как вы можете видеть каждый шаг он рассчитывает нести и толкать его к следующей цифре. И если я возьму базовый >=1000
, результат будет переполнен.
Если вы видите в моем коде, я использую векторы int для представления длинного целого числа. Согласно моей базе число будет разделяться в отдельных частях вектора. Теперь я вижу несколько вариантов:
- использовать
long long
типа для вектора, но он также может быть переполнен для обширных чисел длины - реализует представление переноса в длинной арифметике
После того как я видел некоторые комменты я решил расширить проблему. Предположим, что мы хотим представить наше длинное целое число как вектор ints. Для instanse:
ULLONG_MAX = 18446744073709551615
И для ввода мы передаем число Фибоначчи 210-34507973060837282187130139035400899082304280
, который не соответствует любому типу Stadard. Если мы представим его в виде вектора междунар с базой 10000000 это будет так:
v[0]: 2304280
v[1]: 89908
v[2]: 1390354
v[3]: 2187130
v[4]: 6083728
v[5]: 5079730
v[6]: 34
И когда мы делаем умножение мы можем получить (для простоты пусть это будет два одинаковых номера) (34507973060837282187130139035400899082304280)^2
:
v[0] * v[0] = 5309706318400
...
v[0] * v[4] = 14018612755840
...
Это был только первый ряд, и мы должны сделать шесть таких шагов. Конечно, некоторый шаг вызовет переполнение во время умножения или после вычисления переноса.
Если я что-то пропустил, сообщите мне, и я изменю его. Если вы хотите, чтобы увидеть полную версию, это на мой github
Если у вас есть рабочий код, то, возможно, ваш вопрос лучше подходит для http://codereview.stackexchange.com/? – EdChum
Я голосую, чтобы закрыть этот вопрос как не по теме, потому что он относится к codereview. Там вам нужно будет опубликовать код в своем сообщении, а не ссылаться на ваш github. Вам нужно только разместить соответствующие части. – UmNyobe
Если вы действительно хотите ускорить работу, вам следует использовать еще один более быстрый алгоритм: Toom-Cook, например, преобразование Фурье. –