Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> перевод числа в строку, Аптимизация кода 
:(
    Опции темы
bsa
Дата 28.12.2007, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Lazin, точно. Поторопился и накосячил:
Код
std::string numString = static_cast<std::stringstream&>(std::stringstream() << 12345).str();
Но, имхо, так лучше не делать.
PM   Вверх
baldina
Дата 28.12.2007, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



GIK молчит чего-то. Он тут еще?
Во думаю такой вариант будет довольно шустр:
Код

char* int2str (long value, char *str)
{
  char *p = str;
  if (value < 0) 
  {
    *p++ = '-';
    value = -value;
  }

  for (long v = value; v > 0; ++p)
    v /= 10;
  *p-- = '\0';

  do {
    unsigned digit = value % 10;
    value /= 10;       
    *p-- = digit + '0';
  } while (value > 0);

  return str;
}


PM MAIL   Вверх
Lazin
Дата 28.12.2007, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



В реальном проекте я бы эту ф-ю не использовал, хотя-бы потому-что она не безопасна.
PM MAIL Skype GTalk   Вверх
bsa
Дата 28.12.2007, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Вот мой вариант:
Код
char* intToStr(int value, char *buffer)
{
    char *bb = buffer;
    char *p = buffer;
    if (value < 0) {
        *buffer = '-';
        ++p;
        ++bb;
        value = -value;
    }
    do {
        *bb = (value % 10) + '0';
        value /= 10;
        ++bb;
    }while(value);
    *bb = '\0';
    for(--bb; bb > p; ++p, --bb) {
        const char a = *p;
        *p = *bb;
        *bb = a;
    }
    return buffer;
}
На мой вгляд, работает быстрее раза в 2, чем предыдущий вариант.

Это сообщение отредактировал(а) bsa - 28.12.2007, 22:41
PM   Вверх
W4FhLF
Дата 28.12.2007, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Цитата(bsa @  28.12.2007,  18:09 Найти цитируемый пост)
На мой вгляд, работает быстрее раза в 2, чем предыдущий вариант.


Какой предыдущий? Твой вариант работает в 3 раза медленнее, чем вариант baldina.

Но тут вне конкуренции оказывается функция из дока "Software Optimization Guide for AMDAthlon™ 64 and AMDOpteron™ Processors", на моём процессоре Athlon 64 3500+ она работает в 3 раза быстрее, чема вариант baldina(он в теме самый быстрый). Код немного дописан, чтобы функция понимала так же знаковые числа. 

Код

__declspec(naked) void __stdcall uint_to_ascii_nlz(char *sptr, int x)
{
   __asm {
      push edi                ; Save as per calling conventions.
      push ebx                ; Save as per calling conventions.
      mov  edi, [esp+12]      ; sptr
      mov  eax, [esp+16]      ; x

      cdq             ;if eax >= 0 then edx=0 else edx=-1
      xor eax,edx
      sub eax,edx
      mov byte ptr[edi],'-'
      sub edi,edx   ;if eax < 0 then {inc edi} else {затрем '-' первой цифрой}

      mov  ecx, eax           ; Save original argument.
      mov  edx, 89705F41h     ; 1e-9 * 2^61 rounded
      mul  edx                ; Divide by 1e9 by multiplying with reciprocal.
      add  eax, eax           ; Round division result.
      adc  edx, 0             ; EDX[31-29] = argument / 1e9
      shr  edx, 29            ; Leading decimal digit, 0...4
      mov  eax, edx           ; Leading digit
      mov  ebx, edx           ; Initialize digit accumulator with
                              ;  leading digit.
      imul eax, 1000000000    ; Leading digit * 1e9
      sub  ecx, eax           ; Subtract (leading digit * 1e9) from argument.
      or   dl, '0'            ; Convert leading digit to ASCII.
      mov  [edi], dl          ; Store leading digit.
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      mov  eax, ecx           ; Get reduced argument < 1e9.
      mov  edx, 0abcc7712h    ; 2^28 / 1e8 * 2^30 rounded up
      mul  edx                ; Divide reduced
      shr  eax, 30            ;  argument < 1e9 by 1e8,
      lea  edx, [eax+4*edx+1] ;  converting it into 4.28 fixed-point
      mov  eax, edx           ;  format such that 1.0 = 2^28.
      shr  eax, 28            ; Next digit
      and  edx, 0fffffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-27]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[26-0]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 27            ; Next digit
      and  edx, 07ffffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-26]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[25-0]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 26            ; Next digit
      and  edx, 03ffffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-25]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[24-0]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 25            ; Next digit
      and  edx, 01ffffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-24]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[23-0]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr, No, keep old ptr.
      shr  eax, 24            ; Next digit
      and  edx, 00ffffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-23]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[31-23]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 23            ; Next digit
      and  edx, 007fffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit out to memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-22]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[22-0]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 22            ; Next digit
      and  edx, 003fffffh     ; Fraction part
      OR   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-21]
      lea  edx, [edx*4+edx]   ; 5 * fraction, new fraction EDX[21-0]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 21            ; Next digit
      and  edx, 001fffffh     ; Fraction part
      or   ebx, eax           ; Accumulate next digit.
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], al          ; Store digit in memory.
      lea  eax, [edx*4+edx]   ; 5 * fraction, new digit EAX[31-20]
      cmp  ebx, 1             ; Any nonzero digit yet?
      sbb  edi, -1            ; Yes, increment ptr. No, keep old ptr.
      shr  eax, 20            ; Next digit
      or   eax, '0'           ; Convert digit to ASCII.
      mov  [edi], ax          ; Store last digit and end marker in memory.
      pop  ebx                ; Restore register as per calling convention.
      pop  edi                ; Restore register as per calling convention.
      ret  8                  ; Pop two DWORD arguments and return.
   }
}



--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
bsa
Дата 28.12.2007, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Действительно, мой вариант был медленней, так как оказалось, что функция div() не встраиваемая. Исправил на использование operator/() и operator%(), которые встраиваются.
Результаты:
мой вариант:
real    0m4.324s
user    0m4.288s
sys     0m0.008s
вариант baldina:
real    0m7.971s
user    0m7.944s
sys     0m0.028s

Тестировалось:
Код
int main()
{
        char a[100];
        long i;
        for(i = 0; i < 100000000l; ++i)
                int2str(10000, a);  //intToStr(10000, a);
        return 0;
}


Это сообщение отредактировал(а) bsa - 29.12.2007, 11:15
PM   Вверх
MAKCim
Дата 29.12.2007, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



W4FhLF, 
ассемблер тут не рассматривается


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
W4FhLF
Дата 29.12.2007, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Цитата(MAKCim @  29.12.2007,  10:27 Найти цитируемый пост)
ассемблер тут не рассматривается


т.е. где тут? 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
MAKCim
Дата 29.12.2007, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



W4FhLF, 
в форуме по С++


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
JackYF
Дата 29.12.2007, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Кроме того, ассемблер не переносим.

Добавлено через 1 минуту и 47 секунд
Имеется в виду, на другие железоплатформы smile


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0676 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.