ОБЪЯСНЕНИЕ ПОБОЧНОГО ДОПОЛНИТЕЛЬНОГО МЕТОДА:
Я знаю, что этот вопрос был задан некоторое время назад, но поскольку полный ответ о том, как работает метод bitwiseAdd, не дан, один.
Ключ к пониманию логики, инкапсулированной в bitwiseAdd, находится в связи между сложением операциями и xor и и побитовыми операциями. Это отношение определяется следующим уравнением (см. Приложение 1 для числового примера этого уравнения):
x + y = 2 * (x&y)+(x^y) (1.1)
Или проще:
x + y = 2 * and + xor (1.2)
with
and = x & y
xor = x ^ y
Вы могли заметить что-то знакомое в этом уравнении: переменные и и xor такие же, как те, которые определены в начале bitwiseAdd. Существует также умножение на два, которое в bitwiseAdd выполняется в начале цикла while. Но я вернусь к этому позже.
Позвольте мне также кратко рассказать о побитовом операторе '&', прежде чем мы продолжим. Этот оператор в основном "захватывает" пересечение битовых последовательностей, к которым он применяется. Например, 9 и 13 = 1001 и 1101 = 1001 (= 9). Из этого результата видно, что в результат копируются только те биты, которые являются общими для обеих битовых последовательностей. Из этого следует, что когда две битовые последовательности не имеют общего бита, результат применения к ним '&' дает 0 . Это имеет важное значение для побитового сложения, которое скоро станет ясным
Теперь у нас проблема в том, что уравнение 1.2 использует оператор «+», а bitwiseAdd - нет (оно использует только «^», «&» и «<<»). Так как же заставить «+» в уравнении 1.2 как-то исчезнуть? Ответ: «заставляя» выражения <strong>и возвращать 0. И способ, которым мы это делаем, - рекурсия .
Чтобы продемонстрировать это, я собираюсь повторить уравнение 1.2 один раз (сначала этот шаг может быть немного сложным, но при необходимости есть подробный пошаговый результат в приложении 2):
x + y = 2*(2*and & xor) + (2*and ^ xor) (1.3)
Или проще:
x + y = 2 * and[1] + xor[1] (1.4)
with
and[1] = 2*and & xor,
xor[1] = 2*and ^ xor,
[1] meaning 'recursed one time'
Здесь следует отметить пару интересных вещей. Сначала вы заметили, что концепция рекурсии звучит близко к понятию цикла, как, например, в bitwiseAdd. Эта связь становится еще более очевидной, если учесть, что и [1] и xor [1] : это те же выражения, что и и и xor выражения определены INSIDE цикл while в bitwiseAdd. Также отметим, что возникает закономерность: уравнение 1.4 выглядит точно так же, как уравнение 1.2!
В результате этого дальнейшая рекурсия будет проще простого, если вы сохраните рекурсивную запись. Здесь мы повторяем уравнение 1.2 еще два раза:
x + y = 2 * and[2] + xor[2]
x + y = 2 * and[3] + xor[3]
Теперь следует выделить роль переменной 'temp', найденной в bitwiseAdd: temp позволяет переходить с одного уровня рекурсии на следующий.
Мы также замечаем умножение на два во всех этих уравнениях. Как упоминалось ранее, это умножение выполняется в начале цикла while в bitwiseAdd с использованием операторов и << = 1 </strong>. Это умножение имеет последствия на следующем этапе рекурсии, поскольку биты в и [i] отличаются от битов в и [i] предыдущего этапа (и если вы вспомните небольшую заметку, которую я сделал ранее об операторе '&' вы, наверное, видите, куда это идет сейчас).
Общая форма уравнения 1.4 теперь становится:
x + y = 2 * and[x] + xor[x] (1.5)
with x the nth recursion
Finaly:
Так, когда этот бизнес рекурсии заканчивается точно?
Ответ: заканчивается, когда пересечение между двумя битовыми последовательностями в выражении и [x] уравнения 1.5 возвращает 0 . Эквивалент этого в bitwiseAdd происходит, когда условие цикла while становится ложным. В этот момент уравнение 1.5 становится:
x + y = xor[x] (1.6)
И это объясняет, почему в bitwiseAdd мы возвращаем только xor в конце!
И мы закончили! Довольно умный кусок кода это побитовый. Я должен сказать:)
Надеюсь, это помогло
ПРИЛОЖЕНИЕ:
1) Числовой пример уравнения 1.1
уравнение 1.1 гласит:
x + y = 2(x&y)+(x^y) (1.1)
Чтобы проверить это утверждение, можно привести простой пример, скажем, сложение 9 и 13 вместе. Шаги показаны ниже (побитовые представления в скобках):
У нас есть
x = 9 (1001)
y = 13 (1101)
И
x + y = 9 + 13 = 22
x & y = 9 & 13 = 9 (1001 & 1101 = 1001)
x ^ y = 9^13 = 4 (1001 ^ 1101 = 0100)
Подставляя это обратно в уравнение 1.1, мы находим:
9 + 13 = 2 * 9 + 4 = 22 et voila!
2) Демонстрация первого шага рекурсии
Первое уравнение рекурсии в представлении (уравнение 1.3) говорит, что
если
x + y = 2 * and + xor (equation 1.2)
тогда
x + y = 2*(2*and & xor) + (2*and ^ xor) (equation 1.3)
Чтобы получить этот результат, мы просто взяли 2 * и + xor часть уравнения 1.2 выше и применили к нему сложение / побитовые операнды , заданные уравнением 1.1. Это демонстрируется следующим образом:
если
x + y = 2(x&y) + (x^y) (equation 1.1)
* * +1136 затем * +1137 *
[2(x&y)] + (x^y) = 2 ([2(x&y)] & (x^y)) + ([2(x&y)] ^ (x^y))
(left side of equation 1.1) (after applying the addition/bitwise operands relationship)
Упрощение этого с определениями переменных и и xor уравнения 1.2 дает результат уравнения 1.3:
[2(x&y)] + (x^y) = 2*(2*and & xor) + (2*and ^ xor)
with
and = x&y
xor = x^y
И использование этого же упрощения дает результат уравнения 1.4:
2*(2*and & xor) + (2*and ^ xor) = 2*and[1] + xor[1]
with
and[1] = 2*and & xor
xor[1] = 2*and ^ xor
[1] meaning 'recursed one time'