Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Разделение числа на разряды
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Математика и Физика
Abell
Подскажите, плз, какие алгоритмы вообще существуют для разделения числа на разряды? есть задача, требуется отобразить измеренное значение на семисегментном динамическом дисплее. создал массив по количеству разрядов, в цикле делю исходное число на 10 без остатка, обратно умножаю на 10 и вычитаю из исходного. так все получается, но, может, есть более простые/быстрые пути?
Гвоздик
Подходит обычный перевод десятичного числа в двоично-десятичное: циклическое целочисленное деление исходного десятичного на десять, получившийся остаток от деления выносится на сегмент индикатора, начиная с младшего. Может объясняю немного сумбурно, лучше на примерчике покажу:
238 % 10 = 8 - на младший сегмент
23 % 10 = 3 - на средний сегмент
2 % 10 = 0, отсюда выносим сам разряд тогда = 2 - на старший сегмент
А подпрограммку написать тут труда особого, думаю, не составит. Удачи
dxp
Цитата(Abell @ Dec 19 2006, 16:43) *
Подскажите, плз, какие алгоритмы вообще существуют для разделения числа на разряды? есть задача, требуется отобразить измеренное значение на семисегментном динамическом дисплее. создал массив по количеству разрядов, в цикле делю исходное число на 10 без остатка, обратно умножаю на 10 и вычитаю из исходного. так все получается, но, может, есть более простые/быстрые пути?

Деление на 10 довольно неэффективно на МК, где нет аппаратной операции деления. Намного эффективнее работает схема на основе представления числа в виде полинома Горнера. Цитата из эхо-конференции ru.embedded (эх, хорошие были времена smile.gif):

Цитата
Алгоритм менее простой:десятичный эквивалент числа Х можно получить, сдвигая
двоичное число влево и подавая выдвигаемые двоичные цифры в младший разряд
десятичного регистра. Одновременно со сдвигом двоичного регистра необходимо
удваивать содержимое десятичного регистра. Метод основан на представлении числа
в виде полинома Горнера:
Х=Xn-1*2^(n-1)+Xn-2*2^(n-2)+...+X1*2+X0 - это дв.представление
X=(...(Xn-1*2+Xn-2)*2+...+X1)*2+X0 - это по Горнеру

Абисняю на примере. Имеем дв.код 1111 , т.е. 15
1) выдвигаем влево 1-ю ед. из дв.рг
2) удваиваем сод. дес.рг (0*2=0000_0000)
не забываем, что удвоение - десятичное, т.е. с коррекцией
3) вдвигаем выдв.1 в дес.рг(0000_0001)
4) шаг 1
5) шаг 2 (1*2=0000_0010)
6) шаг 3 (0000_0011)
7) шаг 1
8) шаг 2 (3*2=0000_0110)
9) шаг 3 (0000_0111)
10) шаг 1
11) шаг 2 Внимание! Самое интересное:
в данном случае удвоение происходит так:
т.к. исх.число >= 5 , то вводим коррекцию +3
получаем 0000_1010, удваиваем ЭТО число (0001_0100)
12)шаг 3 (0001_0101) Это что? Вроде бы дв/дес. 15. Hе так ли ?


Я на основе этого алгоритма когда-то слепил для себя подпрограмму для MSP430:

Код
bin2BCD16:

; r11 - bit counter
; r12 - input binary number
; r13 - result (low: 4 digits)
; r14 - addr
; r15 - result (high: 1 digit)

    mov.w   #16,r11
    clr     r13
    clr     r15

;-----------------------------------
convert:
    clr     r10
    rla     r12
    rlc     r10

    dadd.w  r13,r13
    dadd.w  r15,r15
    dadd.w  r10,r13
    dadd.w  #0,r15

    dec     r11
    jne     convert


Это, собственно, код преобразования. Результат получается упаковынный по тетрадам (ниблам). У меня там дальше еще шел код распаковки каждой цифири в отдельный байт, но это к делу уже не относится.

Для AVR есть аналогичная подпрограмма, правда, я ее не писал сам, она идет в какой-то атмеловской аппликухе. Я ее лишь адаптировал для возможности вызова в IAR (под соглашения о вызове подрихтовал). На AVR выходит не так коротко, т.к. он, во-первых, 8-разрядный (а тут 16 бит актуальны), во-вторых, у AVR нет инструкций десятичной коррекции при сложении, а у MSP430 есть. Но принцип везде один и тот же, помедитируйте, разобраться не так сложно.
umup
Есть на С (метод сдвига и десятичной коррекции, возможно,самый быстрый для BCD преобразования).
Описание метода - в книге Титце,Шенк Полупроводниковая схемотехника, стр.320 (http://www.cqham.ru/lib.htm)

Функция bin2bcd32 - преобразование binary -> packed bcd (num_bytes - количество байтов на выходе)

Код
uint32_t bin2bcd32(uint32_t num, uint8_t num_bytes) /**< \brief Convert uint32_t num to packed BCD using num_bytes of number - universal \ingroup ul_math */
{uint32_t ul1=0; /*result*/
uint8_t uc1;
for (uc1=(4-num_bytes);uc1;uc1--) num<<=8; /*adjust input bytes*/
for (uc1=(num_bytes<<3);uc1;uc1--) /*bit shift loop*/
{uint8_t uc2,uc3;
  /*BCD nibbles correction*/
  ul1+=0x33333333;
  for (uc3=4;uc3;uc3--)
  {uc2=(uint8_t)(ul1>>24);
   if (!(uc2&0x08)) uc2-=0x03;
   if (!(uc2&0x80)) uc2-=0x30;
   ul1=ul1<<8; ul1|=uc2;
  }
  /*shift next bit of input and result*/
  ul1<<=1;
  if ((num>>24)&0x80) ul1|=1;
  num<<=1;
}
return(ul1);
}
Alex03
Я вот так это реализовывал:
Код
uint64_t  bin2bcdU64(uint32_t n)
{
    int i;
    uint64_t ll;
    uint64_t ull = 0ULL;

    for(i=0;;i++)
    {
        ull = (ull<<1) | (n>>31);
        n <<= 1;

        if(i==31)
            break;

        ll = ( (ull>>3) | ((ull>>2) & ((ull>>1)|ull) ) ) & 0x1111111111ULL;
        ull += ll | (ll<<1);
    }
    return ull;
}

т.е. Всё 32-х разрядное число в 64-х разрядное, в котором 10 значащих двоичнодесятичных разряда.
Если диапазон входных значений меньше то легко можно упростить/ускорить сократив разрядность переменных и укоротив цикл.

ЗЫ А всётаки кое чё на АСМах красивей! smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.