Возведение в квадрат
сводится к трем умножениям чисел половинной длины.
Метод умножения Карацубы
состоит в том, что четыре умножения сводятся к трём.
Правильно ли я понимаю, что для процессора не программируют возведение в квадрат, а используют тот же метод, что для перемножения разных чисел? Для них же используют метод умножения Карацубы.
function km(a:integer; b:integer):integer;#karatsuba method
var l1,l2,r,d,d2,al,ar,bl,br:integer;
begin
l1:=bit_length(a);
if l1<2 then return a*b; end;
l2:=bit_length(b);
if l2<2 then return a*b; end;
d:=max(l1,l2);
d2:=bit_shift(d,-1);
al:=bit_shift(a,-d2);
ar:=a-bit_shift(al,d2);
bl:=bit_shift(b,-d2);
br:=b-bit_shift(bl,d2);
l1:=km(al, bl);
l2:=km(ar, br);
r:=km(al+ar, bl+br);
r := bit_shift((r-(l1+l2)),d2)+bit_shift(l1,bit_shift(d2,1))+l2;
return r;
end.
Подумал и запрограммировал некий способ возведения в квадрат в функцию sq(n). И получилось, что он работает заметно быстрее. Обе функции дают одинаковый результат в результате исполнения.
Код:
for n:=1 to 1000000 do
if sq(n)<>km(n,n) then
writeln(n," sq<>km");
end;
end.
Вывода строки "sq<>km" тут не случилось.
Результаты:
Код:
==> t := timer();m:=0;
for n:=1 to 1000 do
m:=2*m+1;
s:=km(m,m);
end;
writeln(timer()-t).
80414
-: 1
==> t := timer();m:=0;
for n:=1 to 1000 do
m:=2*m+1;
s:=sq(m);
end;
writeln(timer()-t).
550
-: 1
==> 80414/550.
-: 146.207273
При перемножении чисел Мерсенна более чем в 100 раз быстрее.
Код:
==>t := timer();
for n:=1 to 1000000 do
s:=km(n,n);
end;
writeln(timer()-t).
226362
-: 1
==> t := timer();
for n:=1 to 1000000 do
s:=sq(n);
end;
writeln(timer()-t).
10344
-: 1
==> 226362/10344.
-: 21.8834107
При перемножении последовательных чисел более чем в 20 раз быстрее.
Код и проверка сделаны на Aribas (
http://progopedia.ru/language/aribas/ ).
Возможно, что неправильно запрограммировал метод умножения Карацубы и поэтому разрыв в скорости.
Предлагаю желающим попробовать сочинить две функции и повторить эти опыты с возведением в квадрат в любой из систем. Удастся ли вам повторить эти результаты?