Вы не сказали, что каждое натуральное число должно иметь уникальное представление. Итак, вот еще один вариант. (Я не изобрел его, но я не могу вспомнить, как он называется, поэтому мне пришлось реконструировать, как он работает.)
Представлять числа в виде строк цифр с основанием 2, как в двоичном формате, за исключением того, что вместо того, чтобы ограничиваться цифрами 0 и 1, нам дополнительно разрешено использовать цифру 2. Так, например, число 2 имеет два представления: 10 и 2. .
Чтобы сложить два числа, представленные таким образом, просто сложите их по цифрам без переноса. Ясно, что мы можем сделать это эффективно параллельно (с линейным размером, постоянной глубиной схемы). Что ж, теперь у нас есть проблема: полученное число имеет правильное значение по основанию 2, но его цифры не обязательно будут 0, 1 или 2, но могут достигать 4.
Итак, давайте исправим это с помощью следующего прохода распространения переноса: запишите каждую цифру результата в виде двузначного двоичного числа, где вторая цифра равна 0 или 1, а первая цифра может быть 0, 1 или 2. (Так что 0 -> 00, 1 -> 01, 2 -> 10, 3 -> 11, 4 -> 20.) Теперь «переносим» первую цифру каждого из этих двузначных чисел влево, оставляя за собой вторую цифру, но не выполняя любое другое продолжение результата. Например, если мы начали с числа
314102 (perhaps from the original problem of computing 212001 + 102101)
мы выполняем сумму
11 = 3
01 = 1
20 = 4
01 = 1
00 = 0
10 = 2
-------
1130110
Новое число имеет то же значение по основанию 2, и его цифры теперь находятся в диапазоне от 0 до 3, поскольку они образованы из суммы цифры, которая была 0, 1 или 2, и цифры, которая была 0 или 1. Более того каждая цифра результата зависит только от соответствующей цифры и цифры справа от нее в числе из шага, поэтому это можно реализовать с помощью другого линейного размера, схемы постоянной глубины.
Этого недостаточно, поэтому давайте проделаем тот же проход распространения переноса еще раз. Теперь 4 больше не является возможной входной цифрой, поэтому цифра, которую мы переносим, никогда не может быть 2, только 0 или 1. Таким образом, на этот раз процедура приведет к представлению по основанию 2, в котором используются только цифры 0, 1 и 2, чего мы и хотели. В приведенном выше примере результатом будет 1210110
. (Конечно, любое другое представление с тем же значением базы 2 также будет правильным.)
(Для других комбинаций базовой и максимальной цифр вам может понадобиться только один проход распространения переноса. Например, если вы представляете числа в базе 3, используя цифры 0, 1, 2, 3 и 4, самая большая цифра, появляющаяся в сумме, равна 8. , так что обе цифры, участвующие в проходе распространения переноса, будут в диапазоне 0, 1, 2, а их сумма уже будет не более 4.)
Теперь, если вы хотите выполнить другие операции с этим представлением, например, сравнить два числа на равенство, один из вариантов — преобразовать в двоичный код либо последовательно за линейное время, либо параллельно с помощью быстрого сумматора, как описано в ответе Лиора Когана. На самом деле преобразование этого представления в двоичное по существу эквивалентно проблеме сложения чисел в двоичном виде, поскольку мы можем рассматривать представление, подобное 212001
, как «формальное сложение» 101000 + 111001
. Однако вы, вероятно, не можете проверить равенство в этом представлении с постоянной глубиной, как вы можете для двоичного. Я полагаю, что «сложность» в этом смысле либо сложения, либо проверки на равенство важна, учитывая ваши другие ограничения, хотя я не знаю наверняка.
person
Reid Barton
schedule
15.11.2015
a+b+carry1 = result + carry2
, вы можете вычислитьcarry2
, не глядя наcarry1
в подавляющем большинстве случаев, то есть во всех случаях, когдаmap not a /= b
. Таким образом, вы можете произвести выходной перенос заранее и начать добавлять следующий битовый блок, не дожидаясь предыдущего переноса (в большинстве случаев). - person chi   schedule 15.11.2015data Nat = Bin Nat Nat | Zero | One
, с сопоставлением с натуральными числами, и на которомadd : Nat → Nat → Nat
можно реализовать параллельно, потому что две ветви можно добавить независимо.add (Bin l r) = _ l _ r _; add Zero = _; add One = _;
... что-то в этом роде я имею в виду. - person MaiaVictor   schedule 15.11.2015