ОБЪЯСНЕНИЕ МЕТОДА bitwiseAdd:
Я знаю, что этот вопрос был задан некоторое время назад, но, поскольку не было дано полного ответа о том, как работает метод 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 используется оператор «+», тогда как в побитовом добавлении его нет (используются только «^», «&» и «‹‹»). Так как же сделать так, чтобы «+» в уравнении 1.2 каким-то образом исчез? Ответ: «заставив» выражение and возвращать 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. Эта связь становится еще более очевидной, если учесть, что такое and[1] и xor[1]: это те же выражения, что и and и выражения xor определяют ВНУТРИ цикл 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 с использованием оператора and ‹‹= 1. Это умножение имеет последствия на следующем этапе рекурсии, поскольку биты в and[i] отличаются от битов в and[i] на предыдущем этапе (и если вы помните маленькое примечание, которое я сделал ранее об операторе '&' вы, вероятно, видите, к чему это идет сейчас).
Общая форма уравнения 1.4 теперь принимает вид:
x + y = 2 * and[x] + xor[x] (1.5)
with x the nth recursion
НАКОНЕЦ:
Так когда именно эта рекурсия закончится?
Ответ: он заканчивается, когда пересечение двух последовательностей битов в выражении и[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) говорит, что
if
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. Это демонстрируется следующим образом:
if
x + y = 2(x&y) + (x^y) (equation 1.1)
потом
[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'
person
jule64
schedule
24.11.2012