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

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


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Ну и до кучи - чтобы все варианты были и чтобы было из чего выбирать.
Ведь критерии могут быть разными - если действительно нужно максимальное быстродейстиве (ascii протоколы, например) или минимальный код - тогда лучше всего асм-вариант с умножениями, приведенный Rst7 либо вычитания степеней 10 (где-то я уже приводил свой вариант "без восстановления остатка", когда вычитаются десятки тысяч, потом добавляются единицы тысяч, потом вычитаются сотни и добавляются десятки - каждый раз порогом есть переход через 0 и после этого назад вычитаемое не добавляется - код ещё немного короче и немного быстрее).
Если в программе деление всё равно нужно в других местах (уже линкуется и ещё одно использование на размер не влияет) и преобразование нужно только для пользовательского интерфейса (медленного по сути), то itoa по коду не проигрывает (а то и выигрывает), а его тормознутость не мешает.

Ну а если кроме "лишних полтора килобайта не жалко" (если без плавающих форматов и переменных ширин полей и прочих режко используемых возможностей, про которые не все и знают, то fprintf тянет где-то столько), не хочется компоновать вывод, вручную соображая форматирование - от перемешивания строк и чисел и включая усечение вывода приведенных вариантов до, скажем, 3 знаков, то printf ничем не хуже.
Причём в зависимости от инструмента sprintf (требующий опять таки врукопашную выделять буфер и потом его копировать куда надо) можно отложить и использовать fprintf
avr-gcc
Код
#include <stdio.h>
#include <lcd.h>

int lcd_file_putc(char ch, FILE * stream)
{
    (void) stream;
    lcd_putchar(ch);
    return 0;
}

FILE lcd_file = FDEV_SETUP_STREAM(lcd_file_putc, 0, _FDEV_SETUP_WRITE);
#define flcd (&lcd_file)

...
    // тут и с гашением, и без гашения, и с фиксированной шириной поля, и с переменной
    // - как угодно
    fprintf_P( flcd, PSTR("%d 0x%04X"), -20121, 0xBEEF);


А если ещё и через терминалку общение всё равно идёт

Код
int console_putc(char ch, FILE * stream)
{
    (void) stream;
    uart_putchar(ch);
    return 0;
}

int console_getc(FILE * stream)
{
    (void) stream;
    return uart_getchar();
}

FILE console_file = FDEV_SETUP_STREAM(console_putc, console_getc, _FDEV_SETUP_RW);
#define fconsole (&console_file)

void report_ex_time(const prog_char *header, const prog_char *comment, uint32_t cpu_ticks)
{
    uint32_t ex_time = (cpu_ticks * CPU_TICK_SCALE + 128) / 256;    // CPU ticks to us
    if (comment)
        fprintf_P(fconsole, PSTR("%-38S = %6luus (%S)\n"), header, ex_time, comment);
    else
        fprintf_P(fconsole,  PSTR("%-38S = %6luus\n"), header, ex_time);
}

То и сам fprintf уже не тянет карман, а удобства хватает.
В конце концов у какой-нибудь зачуханной меги32 ресурсов - почитай как у "Электроники-60" в неплохой комплектации, а за мегу128 я и не говорю.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
777777
сообщение Sep 1 2008, 13:01
Сообщение #17


Профессионал
*****

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



У меня сделано два отдельных преобразования: целое в распакованное двоично-десятичное (здесь никаких хитростей нет, просто последовательно вычитаем 10000, 1000, 100 и т.д.) и двоично-десятичное в семисегментный код. Вот на этом этапе и гасятся нули.

CODE
//
// Перекодировка в 7-сегментные цифры
//
// Input:
// R24:R25 - указатель на массив цифр (6 байт)
// R22 - признак гашения ведущих нулей
//
// используются:
// R18
//

BCDto7Segm:ldi r18, 6
mov r26, r24
mov r27, r25
clt
sbrc r22, 0
set ; уст. T - гашение ведущих нулей
conv: ldi r30, lo8(SegmTable)
ldi r31, hi8(SegmTable)
ld r0, X
brtc addx ; если не гасим нули, то получить 7-сегментный код
tst r0 ; если 0
breq cont ; то продолжить
clt ; иначе - прекратить гашение нулей
sub r24, r26
neg r24
dec r24 ; в r24 - позиция последнего погашенного символа
addx: add r30, r0
adc r31, r1
lpm
st X, r0
cont: adiw r26, 1
dec r18
brne conv
brtc exit ; если все нули
sbiw r26, 1
ldi r18, 0x3f; то последний не гасить
st X, r18
ldi r24, 4

exit: ret


Используются соглашение WinAVR, прототип выглядит так:
uint8_t BCDto7Segm(uint8_t*, bool);
В функцию передаются массив из распакованных двоично-десятичных цифр и признак, означающий, требуется ли гашение. Из функции возвращается позиция последнего погашенного символа - она требуется если число отрицательное, тогда вызываемая программа помещает туда минус.

Сообщение отредактировал IgorKossak - Jul 7 2013, 13:18
Go to the top of the page
 
+Quote Post
sKWO
сообщение Jul 7 2013, 11:55
Сообщение #18


Местный
***

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



Цитата(Rst7 @ Aug 31 2008, 19:41) *
Ох, что-то, вы, господа, мрачно тут начали, деление и т.д.

Вот - без лидирующих нулей для unsigned short. Заточена под IAR'овское соглашение о связях.
CODE
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

Чисто из академического интереса попробовал скомпилировать Ваш код. Переменная i - неизвестна. Да и алгоритм гашения моему неокрепшему уму непонятен. если не трудно на пальцах объясните плиз.
Заранее спасибо.


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Jul 7 2013, 12:19
Сообщение #19


Гуру
******

Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047



Какие-то все жутковатые алгоритмы... Я вот всю жизнь делал преобразование в бинарного значения в упакованный BCD, а по ходу распаковки заменял "0" на пробел до первого не-"0".
Go to the top of the page
 
+Quote Post
toweroff
сообщение Jul 7 2013, 13:33
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(rx3apf @ Jul 7 2013, 16:19) *
заменял "0" на пробел до первого не-"0".

вово sm.gif +1
только еще момент один - если дошли до последнего знака и он тоже 0, то его не трогаем
Go to the top of the page
 
+Quote Post
V.K
сообщение Jul 7 2013, 13:50
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 453
Регистрация: 6-05-06
Из: РФ
Пользователь №: 16 841



Никогда не думал, что подобные вопросы могут быть проблемой и достойны обсуждения. Ну, понадобилось гасить - гаси. Сам не люблю незначащих нулей.
Проблема м.б. только в том, если для этого требуются специальные дефицитные процессоры или машинные команды, которых нет в контроллере и можно споими руками изменить устройство контроллера, добавив эти команды.
Go to the top of the page
 
+Quote Post
sKWO
сообщение Jul 7 2013, 14:21
Сообщение #22


Местный
***

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



Цитата(V.K @ Jul 7 2013, 17:50) *
Никогда не думал, что подобные вопросы могут быть проблемой и достойны обсуждения. Ну, понадобилось гасить - гаси. Сам не люблю незначащих нулей.

Каким образом это делаю я привел ещё в первом посту.
повторяю вопрос академический .
Наверное надо было в личку к автору. wink.gif


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
zöner
сообщение Jul 7 2013, 19:33
Сообщение #23


Частый гость
**

Группа: Участник
Сообщений: 195
Регистрация: 16-02-12
Пользователь №: 70 299



вот тут неплохо разжованы разные алгоритмы преобразования: http://we.easyelectronics.ru/Soft/preobraz...lye-chisla.html
для себя вывел самый оптимальный - преобразование в BCD, вывод - справа-налево (начиная с младшей тетрады), для каждой цифры - сдвиг вправо на 4 бита.
гашение лидирующих нолей получается проще пареной репы - как только число стало равно нулю, пишу в буфер пробелы.
понятно, нужно проверять на начальную равность 0, и показать хотя бы один ноль.
установка точки тоже просто - проверяется, равна ли текущая позиция позиции точки, если равна - ставлю, и двигаюсь к следующему разряду.

Сообщение отредактировал zöner - Jul 7 2013, 19:34
Go to the top of the page
 
+Quote Post
Rst7
сообщение Jul 8 2013, 07:42
Сообщение #24


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

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



QUOTE (sKWO @ Jul 7 2013, 14:55) *
Чисто из академического интереса попробовал скомпилировать Ваш код. Переменная i - неизвестна.


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


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
sKWO
сообщение Jul 8 2013, 10:03
Сообщение #25


Местный
***

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



Цитата(Rst7 @ Jul 8 2013, 11:42) *
Ничего удивительного. Ибо Вам не стоило смотреть на сишный код в комментариях, он является остатком рыбы для последующей ручной оптимизации кода, сгенерированного компилятором.

Спасибо. Тогда вопрос снят.


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post

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

 


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


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