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

 
 
> Вопрос С
badik
сообщение Jun 24 2010, 18:29
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 29-11-06
Из: Екатеринбург
Пользователь №: 22 890



Здравствуйте, Вопрос к людям хорошо знающим С.
Понадобилась функция перевода целого числа в строку. Перерыл спрвочник и help - результат 0.
Банальная проблема. Увы. Обраных функций вагон.
Go to the top of the page
 
+Quote Post
8 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 99)
DRUID3
сообщение Jun 24 2010, 18:43
Сообщение #2


山伏
*****

Группа: Свой
Сообщений: 1 827
Регистрация: 3-08-06
Из: Kyyiv
Пользователь №: 19 294



atoi()/itoa(); Или что-то отсюда...


--------------------
Нас помнят пока мы мешаем другим...
//--------------------------------------------------------
Хороший блатной - мертвый...
//--------------------------------------------------------
Нет старик, это те дроиды которых я ищу...
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jun 24 2010, 18:57
Сообщение #3


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Тут или пользоваться sprintf (или её вариантами - смотреть в описании Вашего компилятора) или утянуть откуда-нибудь (я в свой проект включил часть исходников библиотечных функций - под именем НЕ совпадающим с библиотечным).
В книге K&R есть пример функции - переделайте под вывод в строку.

Или вот ещё - как можно поступить, если под рукой нет зубной щётки:

Код
void lcd_menu_value(
    unsigned long freq,
    uint_least8_t width,    // full width
    uint_least8_t comma,        // comma position (from right, inside width)
    uint_least8_t rj        // right truncated
    )
{
    static const prog_uint32_t vals [] =
    {
        100000000,
        10000000,
        1000000,
        100000,
        10000,
        1000,
        100,
        10,
        1,
    };
    const unsigned  char j = (sizeof vals /sizeof vals [0]) - rj;
    unsigned  char i = (j - width);
    unsigned  char z = 1;    // only zeroes


    for (; i < j; ++ i)
    {
        ldiv_t res = ldiv(freq, pgm_read_dword(& vals [i]));

        if (comma == (j - i))
        {
            z = 0;
            ws1602_wrdata('.');
        }
        if (z == 1 && (i + 1) < j && res.quot == 0)
            ws1602_wrdata(' ');    // supress zero
        else
        {
            z = 0;
            ws1602_wrdata('0' + res.quot);
        }
        freq = res.rem;
    }
}

Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 11:29
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



В свое время я задавал такой же вопрос. Получил несколько ответов, в том числе и не очень "полезных и приятных". Сам написал такое:
Код
void si16toad (int16_t Number, char * StrBuf)
{
  char Sign = ' ';
  if (Number > 0) Sign = '+';
  if (Number < 0) {
    Sign = '-';
    Number = -Number;
  }
  StrBuf[6] = '\0';
  signed char i = 5;
  do {
    StrBuf[i--] = Number % 10 + '0';
    Number /= 10;
  } while (Number);
  StrBuf[i] = Sign;
  for (i--; i >= 0; i--) StrBuf[i] = ' ';
}
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 11:38
Сообщение #5


Гуру
******

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



QUOTE (ViKo @ Jun 25 2010, 14:29) *
Сам написал такое

Совет - больше никому "такое" не показывайте, ну если только врагам.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jun 25 2010, 12:15
Сообщение #6


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(zltigo @ Jun 25 2010, 15:38) *
Совет - больше никому "такое" не показывайте, ну если только врагам.

Что же в этой функции такого плохого?
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jun 25 2010, 12:17
Сообщение #7


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Цитата(ViKo @ Jun 25 2010, 15:29) *
В свое время я задавал такой же вопрос. Получил несколько ответов, в том числе и не очень "полезных и приятных". Сам написал такое:

тяжеловесно и потенциально опасно в смысле стрельбы по памяти
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 12:21
Сообщение #8


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 14:38) *
Совет - больше никому "такое" не показывайте, ну если только врагам.

Я хотел приписать, что это один из первых моих "опусов", но подумал, что в качестве примера для изучения сгодится.
Если можете выдать "достойный" образец, прошу!
P.S. У меня знак рисуется непосредственно перед числом, выравнивается по правому краю. А, ну да, можно было применить указатель, но тогда не пришло в голову.
P.P.S. Господа, давайте найдем, наконец, лучшее решение. А то, сколько людей, столько и мнений. Да, я помню высказывание zltigo, что тема избита. Однако...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 12:24
Сообщение #9


Гуру
******

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



QUOTE (sonycman @ Jun 25 2010, 15:15) *
Что же в этой функции такого плохого?

Абсолютно все sad.gif. Написано на уровне диалекта "Эллочки людоедки", лишние действия, вычиcления, циклы.

QUOTE (ViKo @ Jun 25 2010, 15:21) *
давайте найдем, наконец, лучшее решение.

А что такое лучшее? Гуано оно всегда гуано, а лучшее, как минимум требует критериев для оценки. Если, например, скорость, то для AVR и 16bit чисел уж точно делений быть не должно, тем более громоздкого сочетания деления и взятия остатка от деления.
А тема, действительно, избитая донельзя. Повторять мамнадцатый раз не вижу смысла.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 12:31
Сообщение #10


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 15:24) *
...лишние действия, вычиcления, циклы...

Оставил только значимую часть сообщения smile.gif
Лучший способ воспитания - на собственном примере.
Покажите, как надо.
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jun 25 2010, 12:38
Сообщение #11


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(ViKo @ Jun 25 2010, 16:31) *
Оставил только значимую часть сообщения smile.gif
Лучший способ воспитания - на собственном примере.
Покажите, как надо.

Особенно интересно, как можно это реализовать без циклов smile.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 25 2010, 12:41
Сообщение #12


Гуру
******

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



Просто как пример:
Код
unsigned int short2str(char *str, unsigned short v, unsigned int slz)
{
    unsigned int a, b, n = 0;
    unsigned long vi;

    vi = v * 26844UL;
    if(v >= 57074) vi -= 13422;    // Вдруг кто скопипастит без проверки
    for(a = 0; a < 5; a++)
    {
        b = vi >> 28;
        if(b || !slz)
        {
            *str++ = b + '0';
            n++;
            slz = 0;
        }
        vi &= ~(0x0f << 28);
        vi *= 10;
    }
    if(!n)
    {
        *str++ = '0';
        n = 1;
    }
    *str++ = 0;
    return n;
}
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 12:50
Сообщение #13


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 15:24) *
лучшее, как минимум требует критериев для оценки

Я писал для STM32. Виноват, не сказал сразу. Для PIC или AVR написал бы другое "гуано" smile.gif
Критериев, собственно, два - высокое быстродействие и минимальный объем кода. Понятно, что это две крайности, а лучшее лежит где-то посередине.
У вас есть что-нибудь для ARM - Cortex?
И, если можно, выскажитесь о первом примере от Genadi Zawidowsky. И о последующих.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 12:57
Сообщение #14


Гуру
******

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



QUOTE (sonycman @ Jun 25 2010, 15:38) *
Особенно интересно, как можно это реализовать без циклов smile.gif

Ну для этого сначала нужно понимать русский языка, в частности различие между единственным (цикл)и множественным числом (циклы). В данном конкретном случае, когда по неведомым причинам формат фиксирован 6 символами и используются страшные / и % не нужен и единственный цикл.



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 13:06
Сообщение #15


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 15:57) *
В данном конкретном случае, когда по неведомым причинам формат фиксирован 6 символами и используются страшные / и % не нужен и единственный цикл.

int16 укладывается в эти 6 символов, со знаком, ни больше, ни меньше.
В первом цикле вычисляются цифры, во втором забивал пробелами оставшееся место слева. Можно было сразу инициализировать массив пробелами, но было бы ли это эффективнее?
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jun 25 2010, 13:13
Сообщение #16


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(zltigo @ Jun 25 2010, 16:57) *
Ну для этого сначала нужно понимать русский языка, в частности различие между единственным (цикл)и множественным числом (циклы).

Нерусский учит русскому языку? smile.gif

Имхо, не стоит разворачивать циклы, получится мизерная прибавка к скорости, но чувствительно увеличится размер кода.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 25 2010, 13:14
Сообщение #17


Гуру
******

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



Цитата(sonycman @ Jun 25 2010, 17:13) *
Нерусский учит русскому языку? smile.gif

Многим стоило бы поучиться.

Цитата(sonycman @ Jun 25 2010, 17:13) *
Имхо, не стоит разворачивать циклы, получится мизерная прибавка к скорости, но чувствительно увеличится размер кода.

Нужно не разворачивать имеющиеся, а не плодить лишние.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 13:28
Сообщение #18


Гуру
******

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



QUOTE (ViKo @ Jun 25 2010, 15:50) *
У вас есть что-нибудь для ARM - Cortex?

как и для всех других - наиболее часто используется усеченная реализация printf(). Для ARM, кстати, деление и иже с ним, в нем тоже не используются - десятичные числа, в отличии от hex у меня почти всегда немногозначные - на вычитании быстрее.
QUOTE (sonycman @ Jun 25 2010, 16:13) *
Нерусский учит русскому языку? smile.gif

Я с середины шестого класса за границей CCCР в русской школе учился, а учителя там были очень хорошие. После той 'пятерки', особых проблем с грамотностью нет, хотя, конечно, забывается sad.gif.
QUOTE (ViKo @ Jun 25 2010, 16:06) *
во втором забивал пробелами....

Все делать в первом.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 13:34
Сообщение #19


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 16:28) *
как и для всех других - наиболее часто используется усеченная реализация printf(). Для ARM, кстати, деление и иже с ним, в нем тоже не используются - десятичные числа, в отличии от hex у меня почти всегда немногозначные - на вычитании быстрее.

Осталось только выложить его сюда.
Цитата
Я с середины шестого класса за границей CCCР в русской школе учился, а учителя там были очень хорошие.

нужно писать "в отличие"
Цитата
Все делать в первом.

А "минус" и "плюс" потом занести? Неужто эффективнее?
У меня выводится следующим образом:
(upd. добавил еще и 0 для полноты)
Код
"     0"
"   -12"
"+32767"
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 13:39
Сообщение #20


Гуру
******

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



QUOTE (ViKo @ Jun 25 2010, 16:34) *
нужно писать "в отличие"

Про "отличия" не знаю, а там хорошие.
QUOTE (ViKo @ Jun 25 2010, 16:34) *
Осталось только выложить его сюда.

Это уже мое дело.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 13:43
Сообщение #21


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 16:39) *
Про "отличия" не знаю, а там хорошие.

Это у вас синтаксическая ошибка в посте №18

И на этом закончим? Единственное, что я вынес из разговора - надо с указателем повозиться. И к коду aaarrr присмотреться, пока что не понимаю, как работает.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 13:56
Сообщение #22


Гуру
******

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



QUOTE (ViKo @ Jun 25 2010, 16:43) *
Это у вас ошибка в посте №18

Ну это да, предлог 'в отличие' и существительное в предложном падеже с предлогом 'в' sad.gif попутал. Я же говорю - забывается sad.gif. Язык не прост. Не 'C' smile.gif, ну и форум не филологический, а "сишный", к счастью.
QUOTE (ViKo @ Jun 25 2010, 16:43) *
Единственное, что я вынес из разговора - надо с указателем повозиться.

А то, что ДВЕ операции деление и взятие остатка от деления замного будет, не вынесли sad.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 14:04
Сообщение #23


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 16:56) *
Ну это да, предлог 'в отличие' и существительное в предложном падеже с предлогом 'в' sad.gif попутал. Я же говорю - забывается sad.gif . Язык не прост.

Замечу, что я вам на ваши ошибки указал без оскорбительных выражений.
Учу на собственном примере. smile.gif

Цитата(zltigo @ Jun 25 2010, 16:56) *
А то, что ДВЕ операции деление и взятие остатка от деления замного будет, не вынесли sad.gif

О! А как... ?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 14:10
Сообщение #24


Гуру
******

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



QUOTE (ViKo @ Jun 25 2010, 17:04) *
О! А как... ?

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 25 2010, 14:49
Сообщение #25


Гуру
******

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



Цитата(ViKo @ Jun 25 2010, 17:43) *
И к коду aaarrr присмотреться, пока что не понимаю, как работает.

Неправильно, кстати, работает для v >= 59074 biggrin.gif
В качестве отмазки скажу, что таких чисел у меня и не было.

Можно, конечно, компенсатор ошибки округления приделать, типа: if(v >= 57074) vi -= 13422, но это уже некрасиво. Зато для знаковых 16-битных чисел исходный вариант годится без всяких допиливаний smile.gif
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jun 25 2010, 14:55
Сообщение #26


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(zltigo @ Jun 25 2010, 17:56) *
А то, что ДВЕ операции деление и взятие остатка от деления замного будет, не вынесли sad.gif

Хм, но если делать вычитанием, то это будет цикл, а деление нужно сделать только один раз, тем более оно на кортексе аппаратное вроде?
Будет быстрее.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 16:15
Сообщение #27


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 25 2010, 17:10) *
Ну, например, как у Genadi.

А разве в коде Genadi видно, как у него реализована функция ldiv?
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Jun 25 2010, 16:19
Сообщение #28


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Когда то для дисплея (отсюда фиксированное число цифр в числе) делал примерно так:
Код
//-----------Функция преобразования числа в строку----------//
void decbin_5dgt(uint8_t* x, uchar8* buffer)
{
   uint8_t i;
   uint8_t buff[DSPL_BUFF_SIZE]; //промежуточный интовый буфер
  
        for (i=0; i<DSPL_BUFF_SIZE;i++)buff[i]=0; //зануляем
        //разлаживаем
        for (i=*x; i>=10000; i-=10000)buff[0]++;
        for (i=*x-10000*buff[0]; i>=1000; i-=1000)buff[1]++;
        for (i=*x-10000*buff[0]-1000*buff[1]; i>=100; i-=100)buff[2]++;
        for (i=*x-10000*buff[0]-1000*buff[1]-100*buff[2]; i>=10; i-=10)buff[3]++;
        for (i=*x-10000*buff[0]-1000*buff[1]-100*buff[2]-10*buff[3]; i>=1; i-=1)buff[4]++;
    
      
        for (i=0; i<DSPL_BUFF_SIZE;i++)buffer[i]=(uchar8)buff[i]; //переписываем в наш массив                                                }
      
}
//==========================================================//



--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 25 2010, 16:30
Сообщение #29


Гуру
******

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



QUOTE (sonycman @ Jun 25 2010, 17:55) *
Будет быстрее.

На 9999999999 типа, да, а вот на 123? Попробуйте.

QUOTE (ViKo @ Jun 25 2010, 19:15) *
А разве в коде Genadi видно, как у него реализована функция ldiv?

Видно, на что он делит.



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 25 2010, 16:48
Сообщение #30


кекс
******

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



Цитата(ViKo @ Jun 25 2010, 14:29) *
Сам написал такое:void si16toad (int16_t Number, char * StrBuf)


Алгоритм один в один.. Другого наверно и быть не может.
Код
// 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;
}
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 17:16
Сообщение #31


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Goodefine @ Jun 25 2010, 19:19) *
void decbin_5dgt(uint8_t* x, uchar8* buffer)
...

Должно быть uint16_t *x
Go to the top of the page
 
+Quote Post
ssvSerge
сообщение Jun 25 2010, 17:26
Сообщение #32


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

Группа: Участник
Сообщений: 95
Регистрация: 22-01-09
Пользователь №: 43 819



Цитата(defunct @ Jun 25 2010, 19:48) *
Другого наверно и быть не может.

Ух какое обсуждение получилось.
И циклы вам не нравятся и деления - страшны.

Табличные решения должны быть быстрее.
Экономия будет на циклах и на операциях деления.

Каждая операция деления заменяется двеятью сравнениями
в худшем случае. (9ю сравнениями для каждого десятичного
знакоместа).

Вопрос в том на какой таблице остановиться:
Если на десятичной, то таблица будет 36 слов (4знака * 9цифр).
Если на двоичной, то надо будет осуществлять двоично-десятичное сложение.

Двоичная таблица будет медленнее (скорее всего) если есть аппаратный
умножитель. А вот если его нет, то будет быстрее раз эдак в 200 чем
программное деление.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 19:15
Сообщение #33


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Пролистал K&R второе издание от корки до корки, нашел практически такое же "гуано" на языке Элочки Людоедовой, как у меня, defunct, да и Goodefin недалеко от него ушел smile.gif
Раздел 3.6 стр. 77. Те же деление и взятие остатка от деления. С учетом функции reverse - 2 цикла. (замечу в скобках, что книжка эта у меня появилась не так давно, до этого пользовался Шилдтом, но решил "продвинуться", так что любые совпадения - случайны smile.gif)
Еще приводится пример рекурсивного вызова на стр. 100, тоже не скажу, что блещет производительностью.

А табличный способ - самый быстрый. Но и самый жрущий память кода smile.gif Это одна из крайностей. Найти бы еще самый компактный.

P.S. Кстати, автор топика не указал, для чего ему нужна функция itoa. А может, он под Windows пишет, и на производительность и компактность ему одинаково наплевать. smile.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 25 2010, 19:20
Сообщение #34


Гуру
******

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



Цитата(ViKo @ Jun 25 2010, 23:15) *
Найти бы еще самый компактный.

Компактность зависит от архитектуры - если нет аппаратного умножения/деления, самым компактным получится вычитание.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Jun 25 2010, 19:27
Сообщение #35


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



K&R не Ымбеддеры. А zltigo дело говорит вам. К чему там ещё и к словам русского языка придираться то было?


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 19:52
Сообщение #36


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Покопался в своих проектах, нашел преобразование для PIC16. 2 байта преобразовываются в 3 двоично-десятичных упакованных. От которых рукой подать до ASCII. Выдаю кусок из файла. Может кому-то покажется интересным.

Цитата(sigmaN @ Jun 25 2010, 22:27) *
...К чему там ещё и к словам русского языка придираться то было?

Исключительно с целью обучения навыкам культурного ведения диалогов при общении.

Цитата(sigmaN @ Jun 25 2010, 22:27) *
K&R не Ымбеддеры.

А badik , с которого все началось, эмбеддер? Он об этом не говорил.
Прикрепленные файлы
Прикрепленный файл  Bin2BCD.zip ( 550 байт ) Кол-во скачиваний: 25
 
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jun 25 2010, 20:33
Сообщение #37


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата(ViKo @ Jun 25 2010, 20:15) *
А разве в коде Genadi видно, как у него реализована функция ldiv?

А какая разница, как? Между прочим, это функция стандартной библиотеки C. Вместе с div(). В реализации библиотеки от CodeVision отсутствует.
Обычно эти функции инлайнятся, если есть аппаратное деление. После аппаратного (или программного) деления и частное и остаток обычно присутствуют в регистрах процессора и структура ldiv_t (div_t) эти самые регистры впрямую и отображает. Так было на x86. На ARM и AVR не интересовался.

Сообщение отредактировал Genadi Zawidowski - Jun 25 2010, 20:37
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 25 2010, 21:29
Сообщение #38


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Genadi Zawidowski @ Jun 25 2010, 23:33) *
Между прочим, это функция стандартной библиотеки C.

Это я уже понял. Есть ли в Keil для Cortex-M3 не смотрел, надеюсь, есть. Тогда можно будет совместить деление и взятие остатка. Попробую на досуге.
upd. Попробовал. Есть такая функция. Однако после замены деления и взятия остатка на div() размер кода остался тем же. Подробнее буду разбираться позже.
Для ARM интересен вариант от aaarrr - из области трюков и фокусов. Реально полезный пример!
А для процессоров без умножений и делений - вычитание, а на ассемблере - с помощью команд двоично-десятичной коррекции (вот бы на C ее задействовать).
Go to the top of the page
 
+Quote Post
dimka76
сообщение Jun 26 2010, 04:36
Сообщение #39


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Цитата(ViKo @ Jun 25 2010, 23:15) *
Пролистал K&R второе издание от корки до корки


Чутарик не в тему. На форуме все ссылаются на эту книгу. Хотя Дэнис Ричи и является отцом-основателем языка, но это не означает, что он написал хорошую книгу. Мне, например, вот ЭТА очень понравилась.

Теперь по теме. Предлагаю глянуть, что ATMEL предлагает. А глядеть ЗДЕСЬ


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2010, 08:11
Сообщение #40


Гуру
******

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



QUOTE (ViKo @ Jun 25 2010, 22:15) *
Пролистал K&R второе издание от корки до корки, нашел практически такое же "гуано" на языке Элочки Людоедовой

Не обижайте Кернигана sad.gif. Проблема % / это одна частная проблема, которая на некоторых платформах и не проблема - настоятельно
рекомендую откомпилировать и посмотреть на результат работы с 32bit для:
Pentium
Сortex-M3
ARM7
ATmega
ATtiny
Ильфа тоже не обижайте - Эллочкина фамилия была Щукина, а "людоедкой" она была по причине того, что обходилась 30 словами. В чем ее превосходило даже племя людоедов Мумбо-Юмбо, чей словарный запас был 300 слов.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jun 26 2010, 09:04
Сообщение #41


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

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



Цитата(Genadi Zawidowski @ Jun 25 2010, 23:33) *
После аппаратного (или программного) деления и частное и остаток обычно присутствуют в регистрах процессора и структура ldiv_t (div_t) эти самые регистры впрямую и отображает.
Вот именно. Просто всё-таки нужно представлять себе, во что выливается операция / или %, даже если пишешь для x86, как вообще деление реализуется.

Цитата(Genadi Zawidowski @ Jun 25 2010, 23:33) *
Так было на x86. На ARM и AVR не интересовался.
Да так же. Только для AVR в библиотеке компилятора есть функции для деления, которые вызываются и для /, %, только при этом берётся половина результата. А div просто переназначено на эту функцию, возвращающую на регистрах обе части результата деления.
avr-gcc, stdlib.h
Код
/* __divmodhi4 and __divmodsi4 from libgcc.a */
extern div_t div(int __num, int __denom) __asm__("__divmodhi4") __ATTR_CONST__;
extern ldiv_t ldiv(long __num, long __denom) __asm__("__divmodsi4") __ATTR_CONST__;


Так что применение div и тут в два раза сокращает затраты времени на деление по сравнению с раздельной парой /, %. Оптимизатор сам не видит, что можно было бы вызвать еление один раз.
Хотя для данной конкретной задачи для AVR другие способы побыстрее всё равно. Вариант с div, кажется, немного компактнее для случая, когда деление в программе всё равно есть и __divmod* всё равно линкуются.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 26 2010, 09:08
Сообщение #42


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 26 2010, 11:11) *
Не обижайте Кернигана ... настоятельно
рекомендую откомпилировать и посмотреть на результат работы с 32bit для:
...Сortex-M3...

А я для чего написал? STM32. Вот и вы меня "не обижайте". Хоть я и не Керниган.smile.gif
Цитата
Ильфа тоже не обижайте...

Написал, как помнилось. Не входит в сферу моих обязательных знаний, которые нужно периодически обновлять. Наверное, вы правы. Признаю!
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 26 2010, 09:16
Сообщение #43


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



В свое время написал такое:
CODE

/**
* "Указатель" на тетраду байта (обертка над указателем и признаком первая\вторая тетрада)
*/
struct TBCDLocation
{
byte *buf;
bool isFH;

TBCDLocation(byte *buf = 0, bool isFH = true) { this->buf = buf; this->isFH = isFH; }

TBCDLocation& operator++();
TBCDLocation& operator--();
TBCDLocation& operator+=(byte b );
TBCDLocation& operator-=(byte b );
uint_fast16_t operator-(const TBCDLocation& b ) const;
uint_fast16_t operator-(byte *b ) const;
TBCDLocation operator-(uint_fast8_t b ) const;
TBCDLocation operator+(uint_fast8_t b ) const;
bool operator==(const TBCDLocation& b ) const;
bool operator!=(const TBCDLocation& b ) const;
bool operator>(const TBCDLocation& b ) const;

void put(byte val);
void putAndInc(byte val);
void putAndDec(byte val);
byte get();
byte getAndInc();
byte getAndDec();
};

struct TBINtoBCDres
{
TBCDLocation loc; //!< Указатель на цифру перед первой результата
bool isOverflow : 1; //!< признак переполнения
bool isMinus : 1; //!< знак
TBINtoBCDres (TBCDLocation loc, bool isOverflow, bool isMinus) : loc(loc), isOverflow(isOverflow), isMinus(isMinus) {}
};

/**
* Преобразование двоичного числа произвольной длины в десятичное число произвольной длины
* (две цифры в байте). Результат выравнивается по правому краю.
* Заполнение ведущими нулями НЕ производится (в частности, при преобразовании числа 0
* целевой массив НЕ ИЗМЕНИТСЯ вообще и будет возвращен lsBCD).\n
* Если десяичное число не влезает в указанное число разрядов,
* старшие разряды будут потеряны (т.е. 0xffff при преобразовании
* в три разряда даст 535)\n
* Двоичное число лежит младшим байтом вперед. Десятичное - старшей цифрой вперед.
*
* @param lsBCD указатель на младшую цифру результата (самую последнюю)
* @param bin указатель на младший байт двоичного числа (самый первый)
* @param halfbyteCnt
* число тетрад в двоичном числе
* @param bcdDigCnt число цифр в десятичном числе
*
* @return Указатель на цифру перед первой результата и признак переполнения
*/
TBINtoBCDres BINtoBCD(TBCDLocation lsBCD, void const *bin, uint_fast8_t halfbyteCnt, uint_fast8_t bcdDigCnt)
{
// используется сдвиговый алгоритм (полубайты выдвигаются из двоичного регистра и вдвигаются
// в десятичный, при этом произодится коррекция) Число итераций = (число байт) * (число дес цифр)
TBCDLocation msBCD = lsBCD;
bool isOverflow = false;
byte *pbin = ((byte*)bin) + (halfbyteCnt/2)-1;
bool binIsFH = true;
uint_fast8_t tmp;
while(halfbyteCnt--)
{
uint_fast8_t sdv; // выдвинутый полубайт
if (binIsFH)
{
tmp = *pbin--;
sdv = HIGHPART(tmp);
binIsFH = false;
}
else
{
sdv = LOWPART(tmp);
binIsFH = true;
}
TBCDLocation bcd(lsBCD);
while(true) // вдвигаем полубайт в десятичный регистр
{
bool isLim = msBCD == bcd; // признак достижения старшей цифры
if(isLim && sdv == 0) break;

uint_fast8_t cur = isLim ? 0 : bcd.get();
uint_fast8_t tmp = tableBINtoBCD[(cur<<4) | sdv];
cur = HIGHPART(tmp);
sdv = LOWPART(tmp);
if (isLim)
{
if (cur || sdv)
{
if (bcdDigCnt)
{
bcd.putAndDec(cur);
--bcdDigCnt;
msBCD = bcd;
}
else
{
isOverflow = true;
break;
}
}
else
break;
}
else
bcd.putAndDec(cur);
}
}
return TBINtoBCDres(msBCD, isOverflow, false);
}


Таблицу tableBINtoBCD (160 байт) и класс TBCDLocation могу дать, если кому интересно. Написано на С++, но можно переделать на С.

Когда написал, сравнил (на IAR АВР) с двумя алгоритмами - первый использовал деление, второй - вычитание. Цифр уже не помню, но оказался быстрее обоих. Кроме того работает с числами произвольной длины (несколько раз понадобилось smile.gif ) и контролирует переполнение.

Конвертит не в АСКи, а в BCD - две десятичных цифры в байте - но потом легко преобразовать куда надо.

ЗЫ смайлы почему-то парсятся в коде...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2010, 09:18
Сообщение #44


Гуру
******

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



QUOTE (ViKo @ Jun 26 2010, 12:08) *
А я для чего написал?

Вы написали для чего-то на момент написания неназванного. Топикстартер, тоже не сказал для чего. Посему повторяю рекомендации откомпилировать и посмотреть на результат с / % для всех ранее помянутых ядер. Так-же напомню, что слово "гуано" относилось далеко не только к использованию / %.



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jun 26 2010, 09:23
Сообщение #45


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(ReAl @ Jun 26 2010, 13:04) *
Оптимизатор сам не видит, что можно было бы вызвать деление один раз.

Да, я тоже замечал, что функция деления вызывается именно два раза (сначала остаток, потом деление), несмотря на то, что достаточно было бы единственного вызова.

Хотя это было, вроде бы, ещё на AVR. Не знаю, как это будет компилироваться под кортекс и RealView.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 26 2010, 10:24
Сообщение #46


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Следуя рекомендациям, слегка модернизировал код.
Код
void  itoa(int16_t Number, uint8_t *String)
{
  uint8_t  Sign = ' ';
  if (Number > 0) Sign = '+';
  if (Number < 0) {
    Sign = '-';
    Number = - Number;
  }
  String[6] = '\0';
  int8_t i = 5;
  div_t QR = {Number, 0};
  do {
    QR = div(QR.quot, 10);
    String[i--] = QR.rem + '0';
  } while (QR.quot);
  String[i] = Sign;
  for (i--; i >= 0; i--)
    String[i] = ' ';
}

Результат оказался несколько неожиданным smile.gif Ни в первом, ни во втором случае RealView MDK-ARM 4.10 не использует команды деления вообще. А код оказался равным по размеру (и по содержанию, похоже). Так что можно сделать вывод, что / и % компилятор все-же объединил.
А заняла функция деления примерно 80 команд (не машинных тактов, а именно строк в ассемблерном коде).

2 Непомнящий Евгений
На таком принципе основан мой код для PIC, который чуть выше в файле лежит. Только написан на ассемблере.

Цитата(zltigo @ Jun 26 2010, 12:18) *
Посему повторяю рекомендации откомпилировать и посмотреть на результат с / % для всех ранее помянутых ядер. Так-же напомню, что слово "гуано" относилось далеко не только к использованию / %.

Для всех ядер - это вы уж слишком многого от меня хотите. smile.gif У меня и компиляторов таких нет.
А для Cortex-M3 я написал и откомпилировал, и из ваших высказываний так и не понял, что бы такого можно было улучшить в моем коде. А примера, как надо делать, вы не привели.
Go to the top of the page
 
+Quote Post
ssvSerge
сообщение Jun 26 2010, 11:31
Сообщение #47


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

Группа: Участник
Сообщений: 95
Регистрация: 22-01-09
Пользователь №: 43 819



Цитата(ViKo @ Jun 26 2010, 14:24) *
Следуя рекомендациям, слегка модернизировал код.
вы бы озвучили с какой целью модифицировался код.
надо "быстрый алгоритм", "короткий код", "читаемый текст" или еще что-то?

Нужен быстрый и не требовательный алгоритм - в atoi_v1.
слишком длинное решение - посмотрите в atoi_v2.

Операции деления отсутствуют как класс.

P.S. тексты в файлах - написаны за 2 минуты и на работоспособность
не проверялись. демонстрируется метод табличного решения задачи.
ничего более.

P.P.S. метод имеет смысл применять на простых контроллерах без
аппаратного умножителя. (с умножителем надо думать).

Сергей.

Сообщение отредактировал ssvSerge - Jun 26 2010, 11:36
Прикрепленные файлы
Прикрепленный файл  itoa_v1.txt ( 5.72 килобайт ) Кол-во скачиваний: 51
Прикрепленный файл  ito1_v2.txt ( 1.51 килобайт ) Кол-во скачиваний: 82
 
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 26 2010, 13:55
Сообщение #48


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



2 ssvSerge
В ваших алгоритмах число записывается задом наперед, надо iStorePos++; и нет индикации знака числа. А в остальном - можно и так.

Для чего код модернизировал - сделать то, что имею, лучше, оптимальнее. В идеале - оптимальнее и по производительности, и по компактности.

Go to the top of the page
 
+Quote Post
ssvSerge
сообщение Jun 26 2010, 14:19
Сообщение #49


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

Группа: Участник
Сообщений: 95
Регистрация: 22-01-09
Пользователь №: 43 819



Цитата(ViKo @ Jun 26 2010, 16:55) *
В алгоритмах число записывается задом наперед и нет индикации знака числа.

кроме этого нет проверки на 0 и в одном из разрядов нет проверки на "bIsDigitPresent".
Это если уж быть точным. Но это мелочи - код и не претендовал на работоспособность.
Главное, что подход понятен.

Цитата(ViKo @ Jun 26 2010, 16:55) *
код сделать лучше, оптимальнее.

Слово "оптимальнее" следует исключить из лексикона как антинаучное.
Есть критерии: скорость, объем, читабельность и т.д.
Для каждого человека, проекта, процессора критерии изменяются.

Цитата(ViKo @ Jun 26 2010, 16:55) *
В идеале - оптимальнее и по производительности, и по компактности.

ну так озвучьте цифры какой из вариантов (табличный или с делениями)
оптимальнее в конкретно вашем случае. на ваших процессорах и в ваших
глазах.

Сергей.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 26 2010, 14:42
Сообщение #50


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(ssvSerge @ Jun 26 2010, 17:19) *
ну так озвучьте цифры какой из вариантов (табличный или с делениями)
оптимальнее в конкретно вашем случае. на ваших процессорах и в ваших
глазах.

В данный момент меня занимает алгоритм от aaarrr, поискал по компу своему книжку по цифровые трюки, но не нашел. А ведь была. Нельзя ли его расширить, чтобы принимал все числа.
Второй вариант - преобразовать bin в BCD, а затем уже превратить в строку.
Табличный способ меня не привлекает из-за громоздкости.
Точные цифры по быстродействию и размеру кода я не смотрел. Если будет что сказать, доложу.

P.S. Определился, пожалуй, что для меня значит оптимальность. = Компактность кода. А быстродействие мне STM32 и так обеспечит.
P.P.S. Причем, часто бывает, что компактный код и работает быстро.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2010, 15:05
Сообщение #51


Гуру
******

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



QUOTE (ViKo @ Jun 26 2010, 13:24) *
Для всех ядер - это вы уж слишком многого от меня хотите. smile.gif У меня и компиляторов таких нет.

Тем не менее, Вы уже второй раз утверждаете, что писали с оглядкой на Cortex? Лично я воспринял это, как то, что Вы знаете, что творите.
QUOTE
из ваших высказываний так и не понял, что бы такого можно было улучшить в моем коде.

Хорошо,не затрагивая, так сказать основ, только то, что сразу режет глаз.
CODE
void si16toad (int16_t Number, char * StrBuf)
{
  char Sign = ' '; // Зачем-то завели малополезную переменную 'Sign'
  if (Number > 0) Sign = '+';
  if (Number < 0) {
    Sign = '-';
    Number = -Number;
  }
  StrBuf[6] = '\0';
  signed char i = 5; // Cortex говорите? Тогда за не 32 bit переменные, где в этом нет
// небходимости по рукам надо давать. Да и сама переменная лишняя - только команд push/pop добавляет
// А за использование "массивов" вместо указателей - еще один раз
  do {
    StrBuf[i--] = Number % 10 + '0';
    Number /= 10; // 32 bit контроллер? Тогда зачем его беднягу опять без всякой надобности
// заставлять с 16bit 'Number' работать? Сразу несколько лишних команд в цикле
  } while (Number);
  StrBuf[i] = Sign;
// Цикл заполнения пробелами не более, чем 4x ,байтиков. А как это на 32битниках, тем более на
// Cortex это можно сделать одной командой?( ну ладно двумя - одна регистр пробелами заполняет)
  for (i--; i >= 0; i--) StrBuf[i] = ' ';
}



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ssvSerge
сообщение Jun 26 2010, 15:12
Сообщение #52


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

Группа: Участник
Сообщений: 95
Регистрация: 22-01-09
Пользователь №: 43 819



Цитата(ViKo @ Jun 26 2010, 18:42) *
для меня оптимальность = Компактность кода. бывает, что компактный код и работает быстро.
о - вот теперь всё понятно. табличные методы в таких условиях, конечно, проигрывают.

я хотел сказатать только, что таблицу можно сделать на базе "2 в степени" и заниматься
BCD сложением. Значительно компактнее, чем десятичная таблица, и реализация на ASM
проста до смешного. Хотя в скорости, конечно, уступает десятичной.

Сергей.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 26 2010, 15:14
Сообщение #53


Гуру
******

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



Цитата(ViKo @ Jun 26 2010, 18:42) *
В данный момент меня занимает алгоритм от aaarrr, поискал по компу своему книжку по цифровые трюки, но не нашел. А ведь была. Нельзя ли его расширить, чтобы принимал все числа.

Да нет там никаких трюков, кроме обычной арифметики smile.gif Первым умножением число переводится в представление 4.28, дальше все понятно.
Расширить в каком направлении?
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 26 2010, 16:28
Сообщение #54


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 26 2010, 18:05) *
// Зачем-то завели малополезную переменную 'Sign'
// Cortex говорите? Тогда за не 32 bit переменные, где в этом нет
// небходимости по рукам надо давать. Да и сама переменная лишняя - только команд ush/pop добавляет
// А за использование "массивов" вместо указателей - еще один раз
// 32 bit контроллер? Тогда зачем его беднягу опять без всякой надобности
// заставлять с 16bit 'Number' работать? Сразу несколько лишних команд в цикле
// Цикл заполнения пробелами не более, чем 4x ,байтиков. А как это на 32битниках, тем более на
// Cortex это можно сделать одной командой?( ну ладно двумя - одна регистр пробелами заполняет)

Sign - а как же без него, он же потом используется, в пока не известном месте.
32 бита - согласен. Согласен понести наказание (вернее, уже понес smile.gif)
push/pop - разве они там есть?
Массивы вместо указателей - не уверен, не исключаю что в данном случае это одно и то же.
Заполнение пробелами - их может быть разное количество, здесь 32-битовые слова не помогут. Над этим подумаю...

Докладываю - создал тестовый проект, в котором только itoa, компилятор задействовал SDIV. Возрадуемся, братья! smile.gif

2 aaarrr
Про формат 4.28 - что это, где почитать?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2010, 16:40
Сообщение #55


Гуру
******

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



QUOTE (ViKo @ Jun 26 2010, 19:28) *
Sign - а как же без него, он же потом используется, в пока не известном месте.

Можно с большей пользой использовать регистр, например, взять и скопировать в него Ваш 'Number'. При этом
будете работать с этим 32bit, а не 16ише, а плюсики и прочее рисовать потом по 'Number'
QUOTE
push/pop - разве они там есть?

Напихаете разных переменных - будут.
QUOTE
Массивы вместо указателей - не уверен

Ну-ну... Две переменных, вместо одной.
QUOTE
Заполнение пробелами - их может быть разное количество, здесь 32-битовые слова не помогут.

Помогут, помогут - заполняйте до того, как начнете цифирки заносить.


QUOTE (ViKo @ Jun 26 2010, 19:28) *
Возрадуемся, братья! smile.gif

Чему?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 26 2010, 16:51
Сообщение #56


Гуру
******

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



Цитата(ViKo @ Jun 26 2010, 20:28) *
2 aaarrr
Про формат 4.28 - что это, где почитать?

Не надо про него читать, просто 4 старших бита - целая часть, остальные - дробная. Довольно часто используется в виде 1.31 или 1.15
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 26 2010, 17:00
Сообщение #57


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Спасибо всем! На сегодня и завтра - умолкаю. "Работа над ошибками".
Возрадуемся - что в Cortex есть команда деления, которая иногда используется.
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jun 27 2010, 17:02
Сообщение #58


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(ViKo @ Jun 26 2010, 21:00) *
Возрадуемся - что в Cortex есть команда деления, которая иногда используется.

Ещё как используется.
На днях посмотрел, для интереса, как скомпилировались операции (dword / 10) и, следом за ней, (dword % 10).
В первом случае, естественно, UDIV.
А во втором - MLS (Multiply and Subtract) с использованием результата предыдущего вычисления.
Есть такая хитрая и полезная (как раз для этих целей) команда smile.gif

Так что даже не пришлось делать вычитание ручками, RealView сам всё оптимизирует правильно.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jun 27 2010, 18:51
Сообщение #59


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ReAl @ Jun 26 2010, 13:04) *
Так что применение div и тут в два раза сокращает затраты времени на деление по сравнению с раздельной парой /, %. Оптимизатор сам не видит, что можно было бы вызвать еление один раз.
Я видел заплатку для этого случая. Сейчас gcc ИМХО это видит:-)
To ViKo:
Поделитесь насколько itoa будет медленнее Вашего самого лучшего варианта:-)


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
badik
сообщение Jun 28 2010, 17:43
Сообщение #60


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 29-11-06
Из: Екатеринбург
Пользователь №: 22 890



Господа всем огромный привет, ни как не думал, что моя маленькая проблема вызовет такой мощный отклик. Вот уж точно 100 друзей намного лучше..
Тут уважаемые "Местный" и "воинствующий философ" подсказали простое решение sprintf, посмотрел С Шилдта с примером, у меня всё идеальо сработало.
Если не затруднил - осмелюсь ещё поспрашать столь почтенное сообщество. Я в начале ADSP-BF533, BF548



Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 28 2010, 21:09
Сообщение #61


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Прежде, чем писать новое, изучил в отладчике работу обеих моих программ - начальной si16toad и измененной itoa, в которой операции % и / были заменены вызовом библиотечной функции div. Напомню: Keil uVision - RealView MDK-ARM 4.10, STM32F103. Результаты оказались интересными.

После компиляции в окне Build Ouitput для обеих программ выдаются одинаковые размеры для кода - 548 байтов при оптимизации O0 и 536 байтов при оптимизации O3. Почему они одинаковые, не понимаю (см. ниже)?! Размеры данных всех типов тоже одинаковые вообще всегда, но это, как раз, не удивляет.

Посчитал размер обеих функций по листингу C компилятора (есть галочка в настройках генерировать листинг). При O0 для si16toad насчитал 84 байта, для itoa 98 байтов (не считая 14 байтов в самой функции div, это уже в отладчике увидел). При O3 - 80 байтов и 94 байта, соответственно. Причем, при оптимизации O0 в si16toad команда деления использовалась дважды, а при O3 только один раз. В-общем, мой первый вариант оказался компактнее.

Посчитал в отладчике количество тактов. Счетчик тактов виден в окне регистров, засекал значение перед вызовом своей функции и после нее. При O0 si16toad выполнялась за 171 такт, itoa за 232 такта. При O3 - 121 такт и 210 тактов, соответственно. Мой первый вариант оказался еще и быстрее.

Увидел лишние знаковые и беззнаковые расширения для переменных меньше 32 байтов. Вот здесь буду совершенствовать программу. Массив или указатель - тоже проверю. Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.


Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 28 2010, 21:33
Сообщение #62


Гуру
******

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



QUOTE (ViKo @ Jun 29 2010, 00:09) *
Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.

Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее.




--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 28 2010, 21:57
Сообщение #63


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 00:33) *
Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее.

Перед "0" я символ + или - не ставлю (считаю, так "красивее" и "правильнее"), потому и обработка такая в начале программ. Итого _ _ _ _ _ 0 \0.
По поводу размеров и тактов - могу выдать весь проект в заархивированном виде.
В настройках есть какие-то "галочки", которых не трогал. Может, что-то и упустил...
Прикрепленные файлы
Прикрепленный файл  Keil_Temp.zip ( 144.56 килобайт ) Кол-во скачиваний: 14
 
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 28 2010, 22:03
Сообщение #64


Гуру
******

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



QUOTE (ViKo @ Jun 29 2010, 00:57) *
Перед "0" я символ + или - не ставлю

Вы ставите один из 3x символов. Вот и ставьте. Таки 4 smile.gif
QUOTE
По поводу размеров и тактов - могу выдать весь проект в заархивированном виде.

Я говорю об аккуратно написанном, посему про 80 байтов в Вашем варианте верю. Сделайте 60 smile.gif.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 08:29
Сообщение #65


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



2 zltigo
Непременно. smile.gif
Выставил две "галки" - Use Cross-Module Optimization и Use MicroLIB. Общий размер кода сократился до 212 и 324 байтов для первой и второй программ. Причем, такой размер получается со второго раза компиляции. "Все чудесатее и чудесатее." Что эти параметры делают? А на конкретный размер и состав кода пока не смотрел.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 13:48
Сообщение #66


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Код
void  itoad(int number, uint8_t *string)
{
  uint8_t  sign;
  *(int32_t *) string =       ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;
  *(int32_t *)(string + 4) =  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;  
  *(int32_t *)(string += 8) = ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24;
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
  string += 2;
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

Работает с 32-битовыми числами со знаком.
string должна быть 12 байтов для 32-битового числа.
60 байтов (+ 4 байта хранят константу "_ _ 0").
~207 тактов.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 29 2010, 14:18
Сообщение #67


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Jun 29 2010, 16:48) *
Код
*(int32_t *) string =
Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 14:29
Сообщение #68


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Jun 29 2010, 17:18) *
Знатная грабля

А для Cortex-M3? А как надо по вашему мнению?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 14:34
Сообщение #69


Гуру
******

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



QUOTE (Сергей Борщ @ Jun 29 2010, 17:18) *
Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.

Это гнулось под Cortex - такая вот игра.
QUOTE (ViKo @ Jun 29 2010, 16:48) *
60 байтов

Чуть симпатичнее и скорее всего еще короче:
CODE
void  itoad(int number, uint8_t *string)
{
  uint8_t  sign;
  *(uint32_t *) string =       '    ';
  *(uint32_t *)(string + 4) =  '    ';  
  *(uint32_t *)(string += 10) = (uint32_t )"  0";
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
//  string += 2;
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

Осталось первоначальную 16bit оптимизировать.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 14:39
Сообщение #70


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 17:34) *
*(uint32_t *) string = ' ';
*(uint32_t *)(string + 4) = ' ';
Осталось первоначальную 16bit оптимизировать.

Кавычки не двойные?
Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 14:45
Сообщение #71


Гуру
******

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



QUOTE (ViKo @ Jun 29 2010, 17:39) *
Кавычки не двойные?

В первых двух - нет. Возможны warnings, правда, поскольку символ wide получается ИЗ 4x ПРОБЕЛОВ. А так нормально. В третьей - три символа в двойных.
QUOTE
Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.

Автоматически, не значит оптимально.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 17:23
Сообщение #72


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 17:34) *
Код
  *(uint32_t *)(string += 10) = (uint32_t )"  0";

Так - нельзя, пропускается два байта.
С кавычками - понял, но варнинги... как бы удовлетворить требованиям компилятора?
Код
#define  FOUR_SPACES  0x20202020
*(uint32_t *) string = FOUR_SPACES;

Нормально?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 17:40
Сообщение #73


Гуру
******

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



QUOTE (ViKo @ Jun 29 2010, 20:23) *
Так - нельзя, пропускается два байта.

А, да. Что-то ошибся.
Тогда так:
CODE
  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
  string += 2;

Есть шанс на экономию пары байт.

QUOTE
С кавычками - понятно, но варнинги... как бы удовлетворить требованиям компилятора?

Ну, например, отключить их локально прагмой, либо таки (long)" ", но константа займет 8 байт.



QUOTE (ViKo @ Jun 29 2010, 20:23) *
Нормально?

Да.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 18:29
Сообщение #74


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 20:40) *
Код
  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
  string += 2;

Есть шанс на экономию пары байт.

В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель? А, заменить +8 +2 на +4 +4 +2?
upd. Попробовал и так, и сяк, и +10, лучше не становится.

16-битовую хочу попробовать с применением формата 4.28, как у aaarrr. А с тем, что сделал для 32 битов, и не знаю, куда уж дальше "копать" для 16 битов. Я, собственно, с 16-битовой и возился, пока не увидел, что 32-битовая из нее получается практически "даром":)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 18:38
Сообщение #75


Гуру
******

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



QUOTE (ViKo @ Jun 29 2010, 21:29) *
В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель?

Вот как написано, так пробуйте.
QUOTE
что 32-битовая из нее получается практически "даром":)

Полагаю, что там есть как минимум один нюанс - не ухудшить шестнадцатибитовостью ну и чуть поджать за счет меньшего буфера.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 19:52
Сообщение #76


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 21:38) *
Вот как написано, так пробуйте.

Во всех (!) перечисленнных вариантах делается одно и то же: +8 +2
Код
;;;34       *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
000006  600a              STR      r2,[r1,#0]
;;;35       *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
000008  604a              STR      r2,[r1,#4]
00000a  a23b              ADR      r2,|L1.248|
00000c  f8412f08          STR      r2,[r1,#8]!
;;;36       string += 2;
000010  1c89              ADDS     r1,r1,#2
;;;37
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 21:13
Сообщение #77


Гуру
******

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



QUOTE (ViKo @ Jun 29 2010, 22:52) *
Во всех (!) перечисленнных вариантах делается одно и то же: +8 +2
CODE
;;;34       *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
000006  600a              STR      r2,[r1,#0]
;;;35       *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
000008  604a              STR      r2,[r1,#4]
00000a  a23b              ADR      r2,|L1.248|
00000c  f8412f08          STR      r2,[r1,#8]!
;;;36       string += 2;
000010  1c89              ADDS     r1,r1,#2
;;;37

Выложите-ка просто целиком и без редактирования ДВА листинга, как у Вас было и как я предложил. Тогда будет видно.
Пока "идеальный варинат" этого кусочка мог-бы быть такой:
CODE
STR      r2,[r1,#0]
STR      r2,[r1,#4]
ADR      r2,......
STR      r2,[r1,#8]
ADDS     r1,r1,#10

Все команды по 16бит и на два байта меньше относительно приведенного выше варианта.
Но компилятору чего-то у уму заклинило sad.gif
А что будет если так:
CODE
*(uint32_t *)(string + 4) =  '    ';  
  *(uint32_t *)(string + 8 ) = (uint32_t )"  0";
  string += 10;



P.S.
Компильнул IAR-овским компилятором (слега еще подправив,но в общем, как в 73 посте) все, как задумывалось получилось и 54 байта размер кода.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 08:00
Сообщение #78


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Выкладываю ваш вариант.
Последнее, что вы написали, тоже делал.
Пара вопросов, возникших в процессе... -
1. Можно ли "заинлайнить" библиотечную функцию, ту же div, например?
2. Есть ли способ задать массив, выровненный по 4-байтовой границе?

upd.
Вах, получилось!
Код
void  itoad(int number, uint8_t *string)
{
  #define  FOUR_SPACES  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24
  uint8_t  sign;
  
  *(uint32_t *)(string) = FOUR_SPACES;
  *(uint32_t *)(string + 4) = FOUR_SPACES;    
  *(uint32_t *)(string + 8) = (uint32_t)"  0";
  string += 10;
//  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
//  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
//  string += 2;
      
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

58 байтов
Код
;;;31       *(uint32_t *)(string) = FOUR_SPACES;
000002  f04f3220          MOV      r2,#0x20202020
;;;32       *(uint32_t *)(string + 4) = FOUR_SPACES;    
000006  600a              STR      r2,[r1,#0]
;;;33       *(uint32_t *)(string + 8) = (uint32_t)"  0";
000008  604a              STR      r2,[r1,#4]
00000a  a23a              ADR      r2,|L1.244|
;;;34       string += 10;
00000c  608a              STR      r2,[r1,#8]
00000e  310a              ADDS     r1,r1,#0xa

Вроде уже делал так.
Прикрепленные файлы
Прикрепленный файл  keil_temp.txt ( 8.62 килобайт ) Кол-во скачиваний: 82
 
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 09:22
Сообщение #79


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



"Шеф, все пропало!..."
По команде *(uint32_t *)(string + 8) = (uint32_t)" 0";
заносится адрес строки, а не сама строка!

На всякий случай, если кто-то заинтересуется, выдаю работающий код.
Код
void  itoad(int number, uint8_t *string)
{
  #define  TETRASPACE  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24
  #define  TETRATAIL   ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24
  uint8_t  sign;
  *(uint32_t *)(string) = TETRASPACE;
  *(uint32_t *)(string + 4) = TETRASPACE;    
  *(uint32_t *)(string + 8) = TETRATAIL;
  string += 10;
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}


Часть листинга, обратите внимание, стоит команда LDR, а не ADR, как раньше
Код
;;;31       *(uint32_t *)(string) = TETRASPACE;
000002  f04f3220          MOV      r2,#0x20202020
;;;32       *(uint32_t *)(string + 4) = TETRASPACE;    
000006  600a              STR      r2,[r1,#0]
;;;33       *(uint32_t *)(string + 8) = TETRATAIL;
000008  604a              STR      r2,[r1,#4]
00000a  4a3a              LDR      r2,|L1.244|
;;;34       string += 10;
00000c  608a              STR      r2,[r1,#8]
00000e  310a              ADDS     r1,r1,#0xa
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 11:26
Сообщение #80


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



16-битовая версия (на основе 32-битовой)
Код
void  i16toad(int16_t number, uint8_t *string)
{
  #define  TETRASPACE  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24
  #define  TETRATAIL   ' ' | '0' << 8 | '\0'<< 16 | '\0'<< 24
  uint8_t sign;
  int32_t num = (int32_t)number;
  *(uint32_t *)string = TETRASPACE;
  *(uint32_t *)(string + 4) = TETRATAIL;
  string += 5;
  if (!num) return;
  else
    if (num > 0) sign = '+';
    else {
      sign = '-';
      num = -num;
    }
  do {
    *string-- = num % 10 + '0';
  } while (num /= 10);
  *string = sign;  
}

Те же 58 байтов, но нет константы 4-байтовой. 105 тактов для -32767.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jun 30 2010, 11:31
Сообщение #81


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Вот никак не могу понять, почему никто до сих пор не придумал оператор, который возвращает сразу и частное, и остаток.
Ведь они оба образуются при операции деления.
Зачем 2 раза проводить одну и ту же операцию, чтобы взять по очереди две половинки результата?
laughing.gif
Тяжёлое наследие бейсика...


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 11:35
Сообщение #82


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(MrYuran @ Jun 30 2010, 14:31) *
Вот никак не могу понять, почему никто до сих пор не придумал оператор, который возвращает сразу и частное, и остаток.

В 51-й микроЭВМ была. А в Cortex заменяется двумя командами (upd. Вернее, тремя. Исправил код). Дважды не делается.
Код
000022  4602              MOV      r2,r0
000024  fb90f0f3          SDIV     r0,r0,r3
000028  fb032210          MLS      r2,r3,r0,r2
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 13:12
Сообщение #83


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Напоследок - проверил вариант с преобразованием в 4.28, для int16, с той же формой выдачи результата. Получилось 100 байтов, 150 циклов, не лучший способ. В-общем, вариант itoa для Cortex для себя я уже выбрал smile.gif.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 30 2010, 13:34
Сообщение #84


Гуру
******

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



Цитата(ViKo @ Jun 30 2010, 17:12) *
Получилось 100 байтов, 150 циклов, не лучший способ.

Ну, этот способ я выбирал с учетом специфики ARM7 - там картина должна быть противоположной.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 13:44
Сообщение #85


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(aaarrr @ Jun 30 2010, 15:34) *
Ну, этот способ я выбирал с учетом специфики ARM7 - там картина должна быть противоположной.

Я понял.
Сложнее поставить знак в нужное место, и для гашения лидирующих нулей нужна переменная. Зато вместо деления - умножение. В-общем, все наоборот.
Идея интересная - поделить число на 10000 и умножить на 2^28 (для других размерностей можно использовать другие числа, например, для 8-битов - использовать форму 4.12, умножив на 41).
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 30 2010, 19:02
Сообщение #86


Гуру
******

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



QUOTE (ViKo @ Jun 30 2010, 11:22) *
На всякий случай..

Ну если упорно не хотите нормальное сравнение следать, то вот:
CODE
     59          void  itoad(int number, uint8_t *string)
     60          {
   \                     itoad:
   \   00000000   10B4               PUSH     {R4}
     61            int  sign;
     62            *(int32_t *) string =        0x20202020;
   \   00000002   ....               LDR.N    R2,??DataTable1_1;; 0x20202020
   \   00000004   0A60               STR      R2,[R1, #+0]
     63            *(int32_t *)(string += 4) =  0x20202020;  
   \   00000006   4A60               STR      R2,[R1, #+4]
     64            *(int32_t *)(string += 4) =  0x00302020;
   \   00000008   ....               LDR.N    R2,??DataTable1_2;; 0x302020
   \   0000000A   8A60               STR      R2,[R1, #+8]
     65            string += 2;
   \   0000000C   0A31               ADDS     R1,R1,#+10
     66            if (!number) return;
   \   0000000E   78B1               CBZ.N    R0,??itoad_0
     67            if (number > 0) sign = '+';
   \   00000010   0128               CMP      R0,#+1
   \   00000012   AEBF               ITEE     GE
   \   00000014   2B22               MOVGE    R2,#+43
   \   00000016   4042               RSBLT    R0,R0,#+0
   \   00000018   2D22               MOVLT    R2,#+45
     68            else {
     69              number = -number;
     70              sign = '-';
     71            }
     72            do {
     73              *string-- = number % 10 + '0';
   \                     ??itoad_1:
   \   0000001A   0A23               MOVS     R3,#+10
   \   0000001C   90FBF3F4           SDIV     R4,R0,R3
   \   00000020   03FB1400           MLS      R0,R3,R4,R0
   \   00000024   3030               ADDS     R0,R0,#+48
   \   00000026   01F80109           STRB     R0,[R1], #-1
     74            } while (number /= 10);
   \   0000002A   2000               MOVS     R0,R4
   \   0000002C   F5D1               BNE.N    ??itoad_1
     75            *string = sign;
   \   0000002E   0A70               STRB     R2,[R1, #+0]
     76          }
   \                     ??itoad_0:
   \   00000030   10BC               POP      {R4}
   \   00000032   7047               BX       LR             ;; return


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 30 2010, 20:29
Сообщение #87


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 30 2010, 22:02) *
Ну если упорно не хотите нормальное сравнение сделать, то вот:

Вы имеете в виду сравнение кода, или операции сравнения внутри кода? Почему не хочу? Еще как! Листинг я же выдал, там, в файлике keil_temp.txt (он и создается Keil-ом именно в таком виде, с расширением txt). Вот еще раз, после замены типа переменной sign (думал, может в ней дело). С недоумением разглядываю ваш и свой листинги, ничего путного на ум не приходит.
Код
                  itoad PROC
;;;27      ***************************************************************************
****/
;;;28     void  itoad(int number, uint8_t *string)
000000  b510              PUSH     {r4,lr}
;;;29     {
;;;30       #define  TETRASPACE  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24
;;;31       #define  TETRATAIL   ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24
;;;32     //  uint8_t  sign;
;;;33       int  sign;
;;;34       *(uint32_t *)(string) = TETRASPACE;
000002  f04f3220          MOV      r2,#0x20202020
;;;35       *(uint32_t *)(string + 4) = TETRASPACE;    
000006  600a              STR      r2,[r1,#0]
;;;36       *(uint32_t *)(string + 8) = TETRATAIL;
000008  604a              STR      r2,[r1,#4]
00000a  4a62              LDR      r2,|L1.404|
;;;37       string += 10;
00000c  608a              STR      r2,[r1,#8]
00000e  310a              ADDS     r1,r1,#0xa
;;;38       if (!number) return;
000010  2800              CMP      r0,#0
000012  d011              BEQ      |L1.56|
;;;39       if (number > 0) sign = '+';
000014  dd02              BLE      |L1.28|
000016  f04f042b          MOV      r4,#0x2b
00001a  e001              B        |L1.32|
                  |L1.28|
;;;40       else {
;;;41         number = -number;
00001c  4240              RSBS     r0,r0,#0
;;;42         sign = '-';
00001e  242d              MOVS     r4,#0x2d
                  |L1.32|
;;;43       }
;;;44       do {
;;;45         *string-- = number % 10 + '0';
000020  230a              MOVS     r3,#0xa
                  |L1.34|
000022  4602              MOV      r2,r0
000024  fb90f0f3          SDIV     r0,r0,r3
000028  fb032210          MLS      r2,r3,r0,r2
00002c  3230              ADDS     r2,r2,#0x30
00002e  f8012901          STRB     r2,[r1],#-1
;;;46       } while (number /= 10);
000032  2800              CMP      r0,#0
000034  d1f5              BNE      |L1.34|
;;;47       *string = sign;
000036  700c              STRB     r4,[r1,#0]
                  |L1.56|
;;;48     }
000038  bd10              POP      {r4,pc}
;;;49    
                          ENDP

У вас метка itoad играет какую-то роль? Почему-то у меня запоминается в стеке LR, а у вас нет.
У вас в строке 63 должно быть число 0x20202020 или, как написано?
Сравнение number производится по-разному, но я не вижу в исходниках разницы.
И это LDR.N - там действительно будет по 2 байта? Где-то рядом таблица?
Забавно, что байты в машинных кодах в IAR и Keil написаны по-разному. Где младший, где старший?
Еще один прикол - у меня '+' заносится в регистр 4-байтовой командой (потому что не имеет повторяющейся последовательности?), а '-' 2-байтовой. У вас все 2-байтовые.

Неужели IAR настолько лучше Keil?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 30 2010, 21:14
Сообщение #88


Гуру
******

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



QUOTE (ViKo @ Jun 30 2010, 22:29) *
У вас в строке 63 должно быть число 0x20202020 или, как написано?

Следы экспериментов. Все 20
QUOTE
У вас метка itoad играет какую-то роль?

Не у меня, а у ASM - точка входа в эту подпрограмму.
QUOTE
Где-то рядом таблица?

А зачем ей быть далеко? IAR Компилятор сделал все корректно и на 6 байт короче.
QUOTE
Почему-то у меня запоминается в стеке LR

Keil решил сэкономить на BX LR





--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 30 2010, 21:42
Сообщение #89


;
******

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



Цитата(MrYuran @ Jun 30 2010, 14:31) *
Тяжёлое наследие бейсика...

Это просто обязано быть отдано на откуп оптимизатору, иначе ломается синтаксис арифметического выражения. Тернарные операции с двумя значениями - это невозможно использовать.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 1 2010, 08:55
Сообщение #90


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Jun 29 2010, 17:18) *
Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.

Грабли можно избежать, если определить строку в виде объединения байтов и 4-байтовых слов.
2 all:
Как сделать в Keil то же, что и в IAR?

Цитата(zltigo @ Jul 1 2010, 00:14) *
IAR Компилятор сделал все корректно и на 6 байт короче.

Только в таблице у него 8 байтов, а у Keil-а 4. Итого, с учетом таблицы, 60 байтов против 62 байтов.

P.S. А тема-то, действительно, начинает соответствовать своему названию - "Вопрос C" smile.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 1 2010, 11:57
Сообщение #91


Гуру
******

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



QUOTE (ViKo @ Jul 1 2010, 10:55) *
Только в таблице у него 8 байтов

Это дело даже не второе, а третье, ибо байты кода это еще команды которые еще исполняются, а некоторые, типа PUSH/POP нескольких регистров, еще и не за один такт.


QUOTE (ViKo @ Jul 1 2010, 10:55) *
Как сделать в Keil то же, что и в IAR?

Написать на ASM smile.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 1 2010, 12:34
Сообщение #92


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jul 1 2010, 14:57) *
Это дело даже не второе, а третье, ибо байты кода это еще команды которые еще исполняются, а некоторые, типа PUSH/POP нескольких регистров, еще и не за один такт.

Давайте проверим. Число -2147483647 (т.е. -(2^31 - 1), максимально допустимое для функции) Keil преобразовал за 207 тактов (сравнивал счетчик тактов перед вызовом itoad и после нее). Сколько у IAR?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 1 2010, 12:38
Сообщение #93


Гуру
******

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



QUOTE (ViKo @ Jul 1 2010, 14:34) *
Давайте проверим.

smile.gif Думаете дополнительные команды ускорят процесс?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 1 2010, 12:52
Сообщение #94


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jul 1 2010, 15:38) *
smile.gif Думаете дополнительные команды ускорят процесс?

Хочу знать, насколько замедлят.
MOV r2,#0x20202020 выполняется за 1 такт.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 1 2010, 12:55
Сообщение #95


Гуру
******

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



QUOTE (ViKo @ Jul 1 2010, 14:52) *
Хочу знать, насколько замедлят.

Посчитайте на пальцах.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 1 2010, 13:59
Сообщение #96


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jul 1 2010, 15:55) *
Посчитайте на пальцах.

На пальцах до 200? У меня столько пальцев нет smile.gif
Я лучше на бумаге smile.gif и калькуляторе.
А SDIV r0,r0,r3 выполняется за 11 тактов... upd. Не всегда! - обнаружил и 10 тактов, и 9 тактов, похоже, от чисел зависит. О! чем меньше делимое, тем меньше тактов. Видел 4 такта.
... а MLS r2,r3,r0,r2 всего за 2.

Так что на пальцах, извините, никак не посчитать.
Максимальное количество тактов для SDIV заметил 12. Где про такты написано?

2 zltigo
Ну если упорно не хотите нормальное сравнение сделать... smile.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 1 2010, 14:11
Сообщение #97


Гуру
******

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



QUOTE (ViKo @ Jul 1 2010, 15:59) *
2 zltigo
Ну если упорно не хотите нормальное сравнение сделать... smile.gif

Меня интересует результат компиляции - уже четко видна и разница и порядок отличия. А заниматься попугаемерами в симуляторах и иже с ним не собираюсь. Тем более, что железо с его ограничениями отдельная песня.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jul 1 2010, 15:24
Сообщение #98


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(ViKo @ Jul 1 2010, 17:59) *
А SDIV r0,r0,r3 выполняется за 11 тактов... upd. Не всегда! - обнаружил и 10 тактов, и 9 тактов, похоже, от чисел зависит. О! чем меньше делимое, тем меньше тактов. Видел 4 такта.
...
Максимальное количество тактов для SDIV заметил 12. Где про такты написано?

Cortex-M3 Technical Reference Manual
Divide: 2-12 Cycles
DIV timings depend on dividend and divisor. DIV is interruptible (abandoned/restarted), with worst case latency of one cycle.
When dividend and divisor are similar in size, divide terminates quickly. Minimum time is for cases of divisor larger than
dividend and divisor of zero. A divisor of zero returns zero (not a fault), although a debug trap is available to catch this case.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 2 2010, 09:07
Сообщение #99


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Перепробовал все "извращения" со сравнениями и др. в надежде уменьшить количество байтов.
Кто бы мне объяснил, почему в некоторых местах команда MOV r2,... кодируется двумя байтами, а в некоторых четырьмя? И не только эта команда.
Код
;;;63       uint8_t  sign = '+';
000010  222b              MOVS     r2,#0x2b
;;;64       if (!number) return;
000012  2800              CMP      r0,#0
000014  d010              BEQ      |L1.56|
;;;65       if (number < 0) {
000016  da03              BGE      |L1.32|
;;;66         number = -number;
000018  f1c00000          RSB      r0,r0,#0
;;;67         sign = '-';
00001c  f04f022d          MOV      r2,#0x2d
                  |L1.32|
;;;68       }

Как-то связано с операторами перехода по результатам сравнения. Как будто учитывается конвейер.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 2 2010, 18:43
Сообщение #100


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Думаю, хуже не станет, если я доложу, что уменьшил количество тактов для преобразования -2147483647 в строку до 195. Жаль, что не байтов.
Код
void  itoad(int32_t number, uint8_t *string)
{
  *(uint32_t *)(string) = 0x20202020;
  *(uint32_t *)(string + 4) = 0x20202020;
  *(uint32_t *)(string + 8) = 0x00302020;
  string += 10;
  uint8_t  sign = '+';
  if (!number) return;
  if (number < 0) {
    number = -number;
    sign = '-';
  }
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}
Go to the top of the page
 
+Quote Post

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

 


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


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