реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Гашение незначащих нулей, кто как делает?
sKWO
сообщение Aug 31 2008, 10:55
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Пока вижу два варианта вывода числа на ЖКИ с гашением незначащих нулей:
Код
#include <stdlib.h>
div_t dtmp;
char str_tmp[6];
str_tmp[5] = 0;  
  OborotiZaMin = (OborotiZaMinConst + (PPeriod >> 1)) / PPeriod;

#if   0

  dtmp = div(OborotiZaMin, 10);
  str_tmp[4] = dtmp.rem + '0';  
  dtmp = div(dtmp.quot, 10);
  str_tmp[3] = dtmp.rem + '0';  
  dtmp = div(dtmp.quot, 10);
  str_tmp[2] = dtmp.rem + '0';  
  dtmp = div(dtmp.quot, 10);
  str_tmp[1] = dtmp.rem + '0';  
  str_tmp[0] = dtmp.quot + '0';  
// Гашение незначащих нулей
  for (i = 0; i < 4; ++i)
    if (str_tmp[i] == '0')
      str_tmp[i] = ' ';
    else
      break;

#else
  
  i = 0;
  dtmp = div(OborotiZaMin, 10000);
  if (dtmp.quot != 0)
    str_tmp[i++] = dtmp.quot + '0';

  dtmp = div(dtmp.rem, 1000);
  if (i || (dtmp.quot != 0))
    str_tmp[i++] = dtmp.quot + '0';
    
  dtmp = div(dtmp.rem, 100);
  if (i || (dtmp.quot != 0))
    str_tmp[i++] = dtmp.quot + '0';
    
  dtmp = div(dtmp.rem, 10);
  if (i || (dtmp.quot != 0))
    str_tmp[i++] = dtmp.quot + '0';
    
  str_tmp[i++] = dtmp.rem + '0';
  str_tmp[i] = 0;
    
#endif
    // LCD_Write

Дабы на ЖКИ небыло такого, например "0750", а было такое "750".
Какой алгоритм используете?


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
alux
сообщение Aug 31 2008, 12:39
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(sKWO @ Aug 31 2008, 13:55) *
Дабы на ЖКИ небыло такого, например "0750", а было такое "750".
Какой алгоритм используете?

Ваш вариант перегружен громоздкими делениями. Все намного проще. Я немного переработал код уважаемого =AVR=. Теперь эта функция заполняет буфер с начала без лидирующих нулей:
Код
char* itoa(unsigned int val, char *s)
{
  register unsigned int temp;
  register char n=0, atemp=0;
  
  atemp=0; temp=10000; if(val >= temp) {n=1; while(val >= temp) {atemp++; val-=temp;} *s++ = atemp+'0';}  
  atemp=0; temp=1000; if((val >= temp)||(n)) {n=1; while(val >= temp) {atemp++; val-=temp;} *s++ = atemp+'0';}  
  atemp=0; temp=100; if((val >= temp)||(n)) {n=1; while(val >= temp) {atemp++; val-=temp;} *s++ = atemp+'0';}  
  atemp=0; temp=10; if((val >= temp)||(n)) {while(val >= temp) {atemp++; val-=temp;} *s++ = atemp+'0';}
  *s++ = (char)val+'0';                                                                      

  *s = '\0';
  
  return s;
}
Go to the top of the page
 
+Quote Post
pavel-pervomaysk
сообщение Aug 31 2008, 13:26
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 253
Регистрация: 28-12-07
Из: Украина г. Первомайск
Пользователь №: 33 716



я просто сравниваю число , и если оно равняется 0х30 то записываю в то место пробел и все . Работаю на асме , думаю пример тут неуместен ...
Go to the top of the page
 
+Quote Post
aesok
сообщение Aug 31 2008, 13:31
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(sKWO @ Aug 31 2008, 14:55) *
Какой алгоритм используете?


Cтандатные библиотечные функции itoa, utoa, ltoa и ultoa.

Код
#include <stdlib.h>

{
  char str_tmp[6];
  unsigned int OborotiZaMin;
...
  utoa (OborotiZaMin, str_tmp, 10);
...
}


Анатолий.

Сообщение отредактировал aesok - Aug 31 2008, 13:34
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 31 2008, 13:45
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Павлик @ Aug 31 2008, 15:26) *
...если оно равняется 0х30 то записываю в то место пробел и все .

Здорово-то как! Все нули а не только начальные заменить на пробелы smile.gif


Цитата(aesok @ Aug 31 2008, 15:31) *
Cтандатные библиотечные функции itoa, utoa, ltoa и ultoa.

Хорошо написанные они работают хорошо, проблема только в том, что они как-раз и не стандартные ANSI C sad.gif Хотя многие библиотеки имеют. Ну и унивесализм, как по радиксу, так и по количеству цифирей, естественно, пожирает ресурсы.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Aesthete Animus
сообщение Aug 31 2008, 14:09
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317



Ну а кто запрещает пользоваться стандартной snprintf?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 31 2008, 14:11
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Aesthete Animus @ Aug 31 2008, 18:09) *
Ну а кто запрещает пользоваться стандартной snprintf?

Стандартная sprintf весит тяжело.
Go to the top of the page
 
+Quote Post
aesok
сообщение Aug 31 2008, 14:14
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата
Ну и унивесализм, как по радиксу, так и по количеству цифирей, естественно, пожирает ресурсы.


Код сгенерированый GCC для функции itoa предложенной alux, с фиксированым радиксом (которая на самом деле являеться utoa):

Код
.global    itoa
    .type    itoa, @function
itoa:
.LFB0:
.LM1:
.LVL0:
    push r16
    push r17
    push r28
    push r29
/* prologue: function */
/* frame size = 0 */
    movw r28,r24
    movw r16,r22
.LM2:
    ldi r18,hi8(10000)
    cpi r24,lo8(10000)
    cpc r25,r18
    brsh .L2
.LVL1:
    ldi r24,lo8(0)
.LVL2:
    rjmp .L3
.LVL3:
.L2:
.LM3:
    movw r30,r24
    subi r30,lo8(-(-10000))
    sbci r31,hi8(-(-10000))
    movw r24,r30
.LVL4:
    ldi r22,lo8(10000)
    ldi r23,hi8(10000)
    call __udivmodhi4
    movw r28,r24
.LM4:
    movw r24,r30
    ldi r22,lo8(10000)
    ldi r23,hi8(10000)
    call __udivmodhi4
    subi r22,lo8(-(49))
    movw r30,r16
    st Z+,r22
    movw r16,r30
    ldi r24,lo8(1)
.LVL5:
.L3:
.LM5:
    ldi r31,hi8(1000)
    cpi r28,lo8(1000)
    cpc r29,r31
    brsh .L4
    tst r24
    breq .L5
.L4:
    movw r24,r28
.LVL6:
    ldi r22,lo8(1000)
    ldi r23,hi8(1000)
    call __udivmodhi4
    mov r18,r22
    movw r24,r28
    ldi r22,lo8(1000)
    ldi r23,hi8(1000)
    call __udivmodhi4
    movw r28,r24
    subi r18,lo8(-(48))
    movw r30,r16
    st Z+,r18
    movw r16,r30
    ldi r24,lo8(1)
.LVL7:
.L5:
.LM6:
    cpi r28,100
    cpc r29,__zero_reg__
    brsh .L6
    tst r24
    breq .L7
.L6:
    movw r24,r28
.LVL8:
    ldi r22,lo8(100)
    ldi r23,hi8(100)
    call __udivmodhi4
    mov r18,r22
    movw r24,r28
    ldi r22,lo8(100)
    ldi r23,hi8(100)
    call __udivmodhi4
    movw r28,r24
    subi r18,lo8(-(48))
    movw r30,r16
    st Z+,r18
    movw r16,r30
    ldi r24,lo8(1)
.LVL9:
.L7:
.LM7:
    cpi r28,10
    cpc r29,__zero_reg__
    brsh .L8
    tst r24
    breq .L9
.L8:
    movw r24,r28
.LVL10:
    ldi r22,lo8(10)
    ldi r23,hi8(10)
    call __udivmodhi4
    mov r18,r22
    movw r24,r28
    ldi r22,lo8(10)
    ldi r23,hi8(10)
    call __udivmodhi4
    movw r28,r24
    subi r18,lo8(-(48))
    movw r30,r16
    st Z+,r18
    movw r16,r30
.LVL11:
.L9:
.LM8:
    movw r18,r28
    subi r18,lo8(-(48))
    movw r30,r16
    st Z+,r18
.LM9:
    movw r28,r16
.LVL12:
    std Y+1,__zero_reg__
.LM10:
    movw r24,r30
.LVL13:
/* epilogue start */
    pop r29
    pop r28
    pop r17
    pop r16
.LVL14:
    ret
.LFE0:



Код функции uitoa из avr-libc c радиксом:

Код
    X_movw    ZL, r_str_lo; &string
    X_movw    r_lstr_lo, ZL; save &string
    cpi    r_radix, 2; no radix < 2
    brlt    99f
    cpi    r_radix, 37; no radix > 36
    brge    99f    
1:
    mov    r22, r_radix; radix
    clr    r23;  dividend in r25:r24,   divisor in r23:r22
    XCALL    _U(__udivmodhi4);  quotient in r23:r22, remainder in r25:r24
    ;  clobbered: r0, r21, r26, r27
    ;  call-used but preserved: r18,r19,r20,r30,r31
    subi    r24, 0xd0; + '0'
    cpi    r24, 0x3a; > '9' ?
    brlt    10f
    subi    r24, 0xd9; + 'a' - 10 - '0'
10:
    st    Z+, r24; write char to string in reverse order!
    X_movw    r_val_lo,r22; quotient -> dividend
    sbiw    r_val_lo,0; value == 0 ?
    brne    1b
99:
    st    Z, __zero_reg__; terminate string
    X_movw    r_val_lo, r_lstr_lo; restore &string as return value
    XJMP    _U(strrev); reverse string


Обе используют __udivmodhi4, размер strrev используемой в uitoa из avr-libc - 16 инструкций.

Анатолий.

Сообщение отредактировал aesok - Aug 31 2008, 14:35
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 31 2008, 15:09
Сообщение #9


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(aesok @ Aug 31 2008, 18:14) *
Обе используют __udivmodhi4, размер strrev используемой в uitoa из avr-libc - 16 инструкций.

Единственное замечание, что в случае большой загруженности проца, надо __udivmodhi4 срочно менять на поразрядное вычитание числа 10^n.
С точки зрения эргономики - масса вариантов: выравнивание, положение знака, правые незначащие, возникающие, если у Вас фиксированная точка. Лично я руководствуюсь критерием минимальных перемещений выводимого числа, т.к. все числовые поля должны привлекать одинаковое количество внимания оператора. С этой точки зрения, сколько цифр заложено, столько и вывожу, как правило, и ноль или другая цифра - пофиг. Формат- священная корова smile.gif Исключения - имхо, если меняются не числа в фиксированных полях, а целые экраны. Тогда, ессно, пробелы вместо нулей обязательны.
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 31 2008, 15:14
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zltigo @ Aug 31 2008, 19:45) *
Здорово-то как! Все нули а не только начальные заменить на пробелы smile.gif
Зачем все? Как только в строке обнаруживается первый символ отличный от нуля, устанавливаем флаг и все последующие символы в строке отображаем без гашения.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 31 2008, 15:20
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(rezident @ Aug 31 2008, 17:14) *
Как только в строке...

Я комментирую то, что было написано - перечитайте, а не то, что можно было додумать, дописать, и т.д...
Два варианта рецептов, включая Ваш, были приведены уже Автором. Так вот к чему была ремака Павлика это действительно загадка (почти smile.gif ).


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Rst7
сообщение Aug 31 2008, 15:41
Сообщение #12


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Ох, что-то, вы, господа, мрачно тут начали, деление и т.д.

Вот - без лидирующих нулей для unsigned short. Заточена под IAR'овское соглашение о связях.
Код
    RSEG CODE:CODE:NOROOT(1)
    PUBLIC _i2a
//   13 __z void i2a(char *s, UINT16 v)
_i2a:
//   14 {
//   15   UINT8 m0; //R16
//   16   UINT8 m1; //R17
//R18-R20 - 24bit fmul result
//R21 - c,b,a ->06 8D B9
//R22 - zero reg
    CLR    R22
    LDI    R21,0x06
//  v=__multiply_unsigned(m0,0x06)+3;
    MUL    R16,R21
    MOVW    R19:R18,R1:R0
    SUBI    R18,0xFD
    SBCI    R19,0xFF
//  v+=__multiply_unsigned(m1,0x06)<<8;
    MUL    R17,R21
    MOV    R20,R1
    ADD    R19,R0
    ADC    R20,R22
//  v+=__multiply_unsigned(m1,0x8D);
        LDI     R21, 0x8D
        MUL     R17, R21
        ADD     R18, R0
        ADC     R19, R1
    ADC    R20, R22
//  v+=__multiply_unsigned(m0,0x8D)>>8;
        MUL     R16, R21
        ADD     R18, R1
        ADC     R19, R22
    ADC    R20, R22
//  v+=__multiply_unsigned(m1,0xB9)>>8;
    LDI    R16,0x10    ; Counter & flags
    LDI    R21,0xB9
        MUL     R17, R21
        LDI     R21, 10        ; Next multiplicand
        ADD     R18, R1
        ADC     R19, R22
    ADC    R20, R22
    BREQ    ??i2a_0
    SUBI    R20,208
    ST    Z+,R20
    INC    R16
??i2a_0:
//   39     UINT16 hv;
//   40     UINT8 bv;
//   41     bv=v>>8;
        MOV     R17, R19
//   42     v=__multiply_unsigned(v,10);
        MUL     R18, R21
        MOVW    R19:R18, R1:R0
//   43     hv=__multiply_unsigned(bv,10);
        MUL     R17, R21
//   44     v+=(hv&0xFF)<<8;
        ADD     R19, R0
//   45     if (SREG_Bit0) hv+=0x100;
    ADC    R1, R22
//   46     bv=hv>>8;
        MOV     R17, R1
//   47     if ((i|bv)&0x8F)
        MOV     R20, R1
        OR      R20, R16
        ANDI    R20, 0x8F
        BREQ    ??i2a_1
//   48     {
//   49       *s++=bv+'0';
    SUBI    R17,208
    ST    Z+,R17
//   50       i|=1;
//        ORI     R18, 0x01
??i2a_1:
//   51     }
//   52     i<<=1;
    ROL    R16
//   54   while(!SREG_Bit0);
        BRBC    0, ??i2a_0
//   55   *s=0;
        ST      Z, R22
//   56 }
        RET


Правда, требует аппаратного умножителя, но теперь уже и камней нету без него...


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
pavel-pervomaysk
сообщение Aug 31 2008, 15:43
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 253
Регистрация: 28-12-07
Из: Украина г. Первомайск
Пользователь №: 33 716



Я тут спорить не собираюсь , сам начинающий и многого не знаю . Предложил только как вместо числа 0705 вывести на ЖКИ 705 . У меня пример такой приемник чм частота 87.500 - 108.000 гашу первый 0 по ненадобности :

mov data,r0 // копируем 1й символ
cpi data,0x30 // если цифра 0
breq next_dig // записываем пробел
rcall print_char // выврдим на ЖКИ
rjmp next_dig2
next_dig:
ldi data,0x20 // загружаем символ
rcall print_char // выводим на ЖКИ пробел
next_dig2:
mov tmp,dig_1 //
cbr tmp,0xF0 //
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 31 2008, 16:22
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Павлик @ Aug 31 2008, 17:43) *
Предложил только...

Спрашивали-то какой из алгоритмов выбрать или чего еще предложить.
Ну гашение одного единственного первого нуля из пяти для индикации частоты вращения не подходит совсем.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
defunct
сообщение Aug 31 2008, 18:00
Сообщение #15


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Код
// convert and output decimal value
int IntToStrPrint( S32 val )
{
    U8  c, len = 0;
    U8  buf[ 10 ]; // max size for text representation of S32 value

    if (val < 0)
    {
        putchar('-');
        val =  -val;
    }

    do {
        c = val % 10 + '0';
        val /= 10;
        buf[ len++ ] = c;
    } while (val != 0);
    
    while (len)
        putchar(buf[ --len ]);
    return SUCCESS;
}


S32 - signed long
U8 - unsigned char

Предлагаю пользовать этот алгоритм, и просто оптимизировать операцию деления на 10 (y = x / 10).
которая сводится к:

y = x * 0xCCCCCCCD >> 35; для 32-х битных чисел.
y = x * 0xCCCD >> 19; для 16-ти битных
y = x * 0xCD >> 3; для 8-ми битных
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th July 2025 - 09:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01528 секунд с 7
ELECTRONIX ©2004-2016