ФлеймФорумПрограммирование

Double dabble (конверсия двоичных чисел в BCD)

#0
12:59, 26 ноя 2020

Наткнулся тут на забавный алгоритм конверсии двоичных чисел в десятичные с сабжевым названием.
На русском что-то не гуглится как оно должно называться, но вот краткое описание того как он работает с английской вики: https://en.wikipedia.org/wiki/Double_dabble
Проведём алгоритм над байтом - для начала резервируется нужное число бит BCD. Каждой цифре по 4 бита, классика.
Запишем BCD-число пока еще заполненное нулями и конвертируемое число рядом вот так:

Цфр1 Цфр2 Цфр3   Число (дв.)
0000 0000 0000   11110011

А теперь мы делаем следующее: 8 раз вдвигаем двоичное число в BCD-число бит за битом на каждой итерации прибавляя 3 к каждой из цифр которые после сдвига стали больше 4.
Получается вот что:

0000 0000 0000   11110011   Инициализация
0000 0000 0001   11100110   Сдвиг
0000 0000 0011   11001100   Сдвиг
0000 0000 0111   10011000   Сдвиг
0000 0000 1010   10011000   Добавили 3 к единицам, т.к. в них накопилось 7
0000 0001 0101   00110000   Сдвиг
0000 0001 1000   00110000   Добавили 3 к единицам, т.к. в них стало 5
0000 0011 0000   01100000   Сдвиг
0000 0110 0000   11000000   Сдвиг
0000 1001 0000   11000000   Добавили 3 к десяткам, т.к. там накопилось 6
0001 0010 0001   10000000   Сдвиг
0010 0100 0011   00000000   Сдвиг
   2    4    3

ВТФ? :) Действительно всё сошлось.
Поискал объяснения как это работает https://stackoverflow.com/questions/28670539/why-is-the-double-da… rithm-working , но лично мне ничего не зашло - например первое же объяснение говорит про деление на 2 и 10, но мы ведь в алгоритме напротив - умножаем. Хм... Забавно. Кто-нибудь в курсе что тут происходит?

#1
13:17, 26 ноя 2020

=A=L=X=
> например первое же объяснение говорит про деление на 2 и 10, но мы ведь в
> алгоритме напротив - умножаем.
не умножаем, а сдвигаем.
Деление столбиком тоже сдвиг и вычитание, а вычитание и сложение в принципе одно и тоже.
Количество сдвигов соответствует одному делению в столбик, но некоторая магия остается)

#2
13:24, 26 ноя 2020

Tonal
> не умножаем, а сдвигаем.

В пояснениях не раз повторяется, что умножаем на 2 и добавляем 1 если верхний бит в числе подъехал единичный, что действительно тупо сама операция сдвига - 3 в одном. Но объясняторы не раз делают упор на умножении на 2.

> Деление столбиком тоже сдвиг и вычитание, а вычитание и сложение в принципе
> одно и тоже.

Это всё понятно, но не получается понять что происходит конкретно в алгоритме. Он какой то шиворот-навыворот, а взятие остатка от деления которым универсальные конвертеры к примеру работают вообще не просматривается.

#3
13:27, 26 ноя 2020

=A=L=X=
> Кто-нибудь в курсе что тут происходит?

Происходит коррекция результата,  на 6 при переходе из тетрады битов в тетраду (т.к для двоичной системы цена перехода равна 16, а для двоично-десятичной  равна 10)

#4
13:32, 26 ноя 2020

0iStalker
> Происходит коррекция результата, на 6 при переходе из тетрады битов в тетраду

То что коррекция опять таки понятно. Это написано в самом описании алгоритма.
Непонятно как она работает.
Ведь даже навскидку если задуматься, то эта коррекция может много раз происходить с разрядами по мере их сдвига влево, т.к. даже на границах отдельных бит, т.е. понятие цифры/разряда тут вообще какое то плавающее и непонятное.
Понятно только, что за счёт этого 8 исходных бит и могут в итоге расползтись по 12 разрядам BCD - их всё время "взбивают" этой вот коррекцией, причём многократно и в раздробленных битово комбинациях. Бред, но ведь работает...

#5
13:41, 26 ноя 2020

0iStalker
> (т.к для двоичной системы цена перехода равна 16, а для двоично-десятичной
> равна 10)

Ааа... Кажется важная деталь прояснилась - коррекцию и надо делать каждый раз при переходе неких порогов в разрядной сетке, поэтому они многократно и планово запускаются. Хм... Удивительно только почему их там не корёжит при такой простой формулировке "стало больше 5 - корректируем", ведь казалось бы коррекции надо делать только после четырёх прокруток подряд на границах как раз разрядов.

#6
13:45, 26 ноя 2020

=A=L=X=
> Непонятно как она работает.

Вот именно так она и работает, тут нет никаких других действий (и смыслов), при переходе разряда из тетрады в следующую - число в двоичной системе должно увеличиться на 16, вот его и добили до 16, пока оно ещё  не переполнило разрядную сетку BCD

(BIN ) 1100 = (DEC) 12
(BIN)  1100 + 110 = (BCD) 1 0010 =  (DEC) 12

#7
16:03, 26 ноя 2020

А блин, дошло! Вот по этой ссылке нормально разжёвано: https://olduino.files.wordpress.com/2015/03/why-does-double-dabble-work.pdf
Там вообще не надо думать ни про какие разряды. В этом был мой затык - я пытался разглядеть как какие то группы разрядов из бинарного представления перемещаются в BCD-представление.
А нифига, это как раз и завело меня в тупик.
Всё что тут происходит же на самом деле это полная реконструкция числа методом умножения на 2, но в BCD-кодировке. Фактически никакие разряды тут не перетекают никуда, а просто полностью реконструируются. Мы просто сразу воссоздаём число в BCD-кодировке, просто из-за гениальности алгоритма это выглядит как "перетекание" двоичного числа в BCD - и в каком то смысле конечно так и есть, но на деле мы просто полностью его реконструируем просто проводя умножение на 2 с возможным добавление единицы тупо потому что суть числа не меняется в какой форме оно выражено.
Т.е. еще раз: каждый шаг алгоритма это не более чем умножение на 2 в BCD-кодировке с возможным добавлением единицы чтобы восстановить число по его полиноминальному разложению по степеням двойки чем оно является в бинарном представлении. А умножение на 2 можно рассматривать как сложение само с собой откуда легко и понять как делаются совершенно типовые BCD-коррекции.
Мда, а показалось прямо лютой битовой магией!

ФлеймФорумПрограммирование

Тема в архиве.