Это широко варьируется в зависимости от процессора и (в некоторых случаях) типа (типов) операндов.
Старые / более простые процессоры обычно используют алгоритм умножения примерно так:
integer operator*(integer const &other) {
unsigned temp1 = other.value;
unsigned temp2 = value;
unsigned answer = 0;
while (temp1 != 0) {
if (temp1 & 1)
answer += temp2;
temp2 <<= 1;
temp1 >>=1;
}
return integer(answer);
}
Поскольку цикл выполняется только тогда, когда / если temp1 != 0
, цикл, очевидно, не будет выполняться, если temp1
начинается с 0 (но, как написано здесь, не будет пытаться оптимизировать для другого операнда, являющегося 0).
Это, однако, по сути, алгоритм по одному. Например, при умножении 32-битных операндов, если каждый бит имеет шанс установки 50:50, мы ожидаем в среднем приблизительно 16 итераций.
Более новый высокопроизводительный ЦП, как правило, будет работать по крайней мере с двумя битами за раз, и, возможно, даже более того. Вместо одного аппаратного обеспечения, выполняющего многократные итерации, как правило, конвейеризация операции выполняется с отдельным (хотя и практически идентичным) оборудованием для каждого этапа умножения (хотя обычно они не отображаются в виде отдельных этапов на обычной конвейерной диаграмме). для процессора).
Это означает, что выполнение будет иметь одинаковую задержку (и пропускную способность) независимо от операндов. В среднем это немного увеличивает задержку и пропускную способность, но приводит к тому, что все операции выполняются с одинаковой скоростью, независимо от операндов.