Редактировать
Давайте посмотрим на второй опубликованный алгоритм, начиная с:
int nearest_power = 2 ^ (floor(log2(multiplier)));
Я считаю, что вычисление log2, довольно приятно, O (log2 (множитель))
, тогда next_power достигает интервала [множитель / 2 к множителю], величина которого равна множителю / 2.Это то же самое, что найти старший установочный бит для положительного числа.
Таким образом, цикл for
равен O (множитель / 2), получается константа 1/2, поэтому это O (n)
В среднем это половина интервала, что будет O (множитель / 4).Но это всего лишь константа 1/4 * n, поэтому она все равно O (n), константа меньше, но все равно O (n).
Более быстрый алгоритм.
Наша интуиция заключается в том, что мы можем умножить число на n цифр за n шагов
В двоичном коде это использует 1-битный сдвиг, 1-битный тест и двоичное сложение для построения полного ответа.Каждая из этих операций является O (1).Это длинное умножение, по одной цифре за раз.
Если мы используем O (1) операций для n, x битного числа, это O (log2 (n)) или O (x), где x - это количество бит в числе
Это алгоритм O (log2 (n)):
int mult(int multiplicand, int multiplier) {
int product = 0;
while (multiplier) {
if (multiplier & 1) product += multiplicand;
multiplicand <<= 1;
multiplier >>= 1;
}
return product;
}
По сути, это то, как мы делаем длинное умножение.
Конечно, разумнее всего использоватьменьшее число в качестве множителя.(Я оставлю это в качестве упражнения для читателя: -)
Это работает только для положительных значений, но путем проверки и запоминания знаков ввода, работы с положительными значениями, а затем корректировки знака,это работает для всех номеров.