Как Реализовать atoi без стандартных библиотек
От: Tirael Туркмения  
Дата: 02.11.04 21:12
Оценка:
В общемто сабж, а да к исходникам не отылать смотрел ничего не понял да и еще там тоже стандартные библы юзаються

Censored. П. 6. -- ПК
Re: Как Реализовать atoi без стандартных библиотек
От: Carc Россия https://vk.com/gosha_mazov
Дата: 02.11.04 21:40
Оценка:
Здравствуйте, Tirael, Вы писали:

T>В общемто сабж, а да к исходникам не отылать смотрел ни хера не понял да и еще там тоже стандартные библы юзаються

ну можно в принципе перебирать каждый символ, проверять его какое нить ASCII-код и формировать число. Только такое решение не очень будет переносимым имхо. А если для винды то в ней есть функции которые проверяют является ли char цифрой, что то вроде IsAlphaNum но точно не помню
Aml Pages Home
Re: Как Реализовать atoi без стандартных библиотек
От: jedi Мухосранск  
Дата: 02.11.04 21:46
Оценка: 1 (1)
Здравствуйте, Tirael, Вы писали:

T>В общемто сабж, а да к исходникам не отылать смотрел ни хера не понял да и еще там тоже стандартные библы юзаються


int atoi(const char *s)
{
int i = 0;
while (*s && *s >= '0' && *s <= '9')
{
i *= 10;
i += *s++ — '0';
}
return i;
}

естественно невалидные символы можно обрабатывть по-другому.
Кроме того нужно добавить проверку на переполнение +
проверку на то что первый символ может быть минусом.
А да, еще можно скипать пробелы впереди.
Но основная идея я надеюсь понятна.
Re: Как Реализовать atoi без стандартных библиотек
От: _Winnie Россия C++.freerun
Дата: 02.11.04 22:20
Оценка:
Здравствуйте, Tirael, Вы писали:

T>В общемто сабж, а да к исходникам не отылать смотрел ни [****] не понял да и еще там тоже стандартные библы юзаються


Нарожал...
Спать пора, а я [*****] занимаюсь
Вот как imho должна выглядить библиотека вывода, которая не привязывает пользователя к iostream. Куда хотим, туда и печатаем, хоть в char*, хоть в std::vector, хоть в поток.

Кстати, в 5 раз быстрее стандартного atoi, если печать в массив.

//(c)_Winnie.

namespace detail
{
  template <class CharT>
  inline char DigitToChar(int i) { return CharT('0'+i); }

  template <class CharT>
  inline CharT Minus() { return '-'; }  
  
  template <class CharT>
  inline CharT Plus() { return '+'; }

  template <class CharT>
  inline CharT Space() { return ' '; }

  inline int DivideBy10(int n)
  {
    struct sizeof_int_4  { int assert[sizeof(int) == 4 ? 1 : -1]; };
    const int magic32 = -858993459;
    return (magic32*n) >> 1; //division by 10;
  }
}

enum PrintPlus
{
  PrintPlusAsBlank=0,
  PrintPlusAsPlus=1,
  PrintPlusAsSpace=2
};

template <class OutIter>
OutIter Print(int i, OutIter out, PrintPlus print_plus= PrintPlusAsBlank)
{
  typedef char CharT;

  bool print_zero = false; //do not print leading zeroes. do print internal zeroes;
  struct sizeof_int_4  { int assert[sizeof(int) == 4 ? 1 : -1]; };
  int n = 1000000000;

  if (i < 0)
  {
    *out++ = detail::Minus<CharT>();
    i= -i;
  }
  else
  {
    if (print_plus)
    {
      *out= print_plus == PrintPlusAsPlus ? detail::Plus<CharT>() : detail::Space<CharT>();
    }
  }

  if (i == 0x80000000)
  {
    int ix80000000[10]= {2,1,4,7,4,8,3,6,4,8};
    for(int digit_num=0; digit_num<10; ++digit_num)
      *out++= detail::DigitToChar<CharT>(ix80000000[digit_num]);
     return out;
  }

  {
    int nn= n; 
    int digit= 0; //digit is in [0..9] range
    while (i >= nn && nn>0) //"nn+= n" may cause overflow
    {
      ++digit;
      nn+= n;
    }

    if (digit)
      print_zero= true;
    nn-= n;
    if (print_zero)
      *out++ = detail::DigitToChar<CharT>(digit);
    i-= nn;
    n= detail::DivideBy10(n);
  }
  for(int digit_num=0; digit_num<8; ++digit_num)
  {
    int nn= n; 
    int digit= 0; //digit is in [0..9] range
    while (i >= nn) 
    {
      ++digit;
      nn+= n;
    }

    if (digit)
      print_zero= true;
    nn-= n;
    if (print_zero)
      *out++ = detail::DigitToChar<CharT>(digit);
    i-= nn;
    n= detail::DivideBy10(n);
  }
  {
    int nn= n; 
    int digit= 0; //digit is in [0..9] range
    while (i >= nn) 
    {
      ++digit;
      nn+= n;
    }
    *out++ = detail::DigitToChar<CharT>(digit);
  }
  return out;
}



#include <time.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <typeinfo>

int main()
{
  char buf[1000];
  char buf2[1000];

  Print(-10, Print(20, buf)); //print 20-10 to buf

  std::vector<char> v;
  Print(0x80000000, std::back_inserter(v));
  v.push_back(0);
  std::wcout <<&v[0];

  std::vector<wchar_t> str;
  Print(123, std::back_inserter(str));
  Print(-123, std::back_inserter(str));
  Print(0, std::back_inserter(str));
  Print(123, std::back_inserter(str), PrintPlusAsBlank);
  Print(123, std::back_inserter(str), PrintPlusAsPlus);
  Print(123, std::back_inserter(str), PrintPlusAsSpace);
  str.push_back(0);
  std::wcout <<&str[0] <<'\n';

  {
    clock_t t= clock();
    for (int i=0; i<0x1000000;++i)
    {
      Print(-1000000000, buf);
    }
    std::cout <<clock() - t <<'\n';
  }

  {
    clock_t t= clock();
    for (int i=0; i<0x1000000;++i)
    {
      itoa(-1000000000, buf, 10);
    }
    std::cout <<clock() - t <<'\n';
  }

  return 0;  
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re[2]: Как Реализовать atoi без стандартных библиотек
От: _Winnie Россия C++.freerun
Дата: 02.11.04 22:43
Оценка: :))
Здравствуйте, _Winnie, Вы писали:

Так, я перепутал все наооборот
Правильно работающая программа — просто частный случай Undefined Behavior
Re[2]: Как Реализовать atoi без стандартных библиотек
От: MaximE Великобритания  
Дата: 03.11.04 07:52
Оценка:
On Tue, 02 Nov 2004 22:20:05 GMT, _Winnie <23256@news.rsdn.ru> wrote:

>   inline int DivideBy10(int n)
>   {
>     struct sizeof_int_4  { int assert[sizeof(int) == 4 ? 1 : -1]; };
>     const int magic32 = -858993459;
>     return (magic32*n) >> 1; //division by 10;
>   }


А зачем этот трюк с умножением на magic32 и последующим сдвигом? Это намного быстрее простого деления?

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re: Как Реализовать atoi без стандартных библиотек
От: maximilian Украина  
Дата: 03.11.04 08:00
Оценка:
Здравствуйте, Tirael, Вы писали:

T>В общемто сабж, а да к исходникам не отылать смотрел ничего не понял да и еще там тоже стандартные библы юзаються


Далеко ходить не нужно, можно, например, реализацию у WTL позаимствовать:

atlmisc.h

    static int _cstrtoi(const TCHAR* nptr)
    {
        int c;              /* current char */
        int total;          /* current total */
        int sign;           /* if '-', then negative, otherwise positive */

        while ( _cstrisspace(*nptr) )
            ++nptr;

        c = (int)(_TUCHAR)*nptr++;
        sign = c;           /* save sign indication */
        if (c == _T('-') || c == _T('+'))
            c = (int)(_TUCHAR)*nptr++;    /* skip sign */

        total = 0;

        while (_cstrisdigit((TCHAR)c)) {
            total = 10 * total + (c - '0');     /* accumulate digit */
            c = (int)(_TUCHAR)*nptr++;    /* get next char */
        }

        if (sign == '-')
            return -total;
        else
            return total;   /* return result, negated if necessary */
    }


Ф-ции _cstrisdigit и _cstrisspace будут работать только под Win, поэтому для Win-независимости придется написать свои аналоги.

    static int _cstrisdigit(TCHAR ch)
    {
        WORD type;
        GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
        return (type & C1_DIGIT) == C1_DIGIT;
    }
    static int _cstrisspace(TCHAR ch)
    {
        WORD type;
        GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
        return (type & C1_SPACE) == C1_SPACE;
    }
Re[3]: Как Реализовать atoi без стандартных библиотек
От: alnsn Великобритания http://nasonov.blogspot.com
Дата: 03.11.04 08:56
Оценка: :)
Здравствуйте, MaximE, Вы писали:

ME>А зачем этот трюк с умножением на magic32 и последующим сдвигом? Это намного быстрее простого деления?


Наверно ему очень книга www.hackersdelight.org понравилась
Re[4]: Как Реализовать atoi без стандартных библиотек
От: MaximE Великобритания  
Дата: 03.11.04 09:05
Оценка:
On Wed, 03 Nov 2004 08:56:11 GMT, alnsn <21403@news.rsdn.ru> wrote:

> ME>А зачем этот трюк с умножением на magic32 и последующим сдвигом? Это намного быстрее простого деления?

>
> Наверно ему очень книга www.hackersdelight.org понравилась



Я хочу узнать действительно ли умножение быстрее деления? Если бы это было сложение и сдвиг, то да, но вот умножение вместо деления...

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re[5]: Как Реализовать atoi без стандартных библиотек
От: yxiie Украина www.enkord.com
Дата: 03.11.04 09:23
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Я хочу узнать действительно ли умножение быстрее деления? Если бы это было сложение и сдвиг, то да, но вот умножение вместо деления...


для float однозначно быстрее, для int скорее всего быстрее
при умножении не может быть вызвано прерывание "деление на ноль", что уже говорит о том, что операция проще.
... << RSDN@Home 1.1.3 stable >>
Re[5]: Как Реализовать atoi без стандартных библиотек
От: alnsn Великобритания http://nasonov.blogspot.com
Дата: 03.11.04 10:55
Оценка: 20 (1)
Здравствуйте, MaximE, Вы писали:

ME>On Wed, 03 Nov 2004 08:56:11 GMT, alnsn <21403@news.rsdn.ru> wrote:


>> ME>А зачем этот трюк с умножением на magic32 и последующим сдвигом? Это намного быстрее простого деления?

>>
>> Наверно ему очень книга www.hackersdelight.org понравилась

ME>


ME>Я хочу узнать действительно ли умножение быстрее деления? Если бы это было сложение и сдвиг, то да, но вот умножение вместо деления...


// test.c
int magic(int n)
{
    int magic32 = -858993459;
    return (magic32*n) >> 1; //division by 10;
}

int divide10(int n)
{
    return n / 10;
}

int divide(int n, int m)
{
    return n / m;
}

int main()
{
    magic(100);
    divide10(100);
    divide(100, 10);
    return 0;
}



$ gcc -O2 test.c
$ objdump -s a.out


08048310 <magic>:
 8048310:       55                      push   %ebp
 8048311:       89 e5                   mov    %esp,%ebp
 8048313:       8b 45 08                mov    0x8(%ebp),%eax
 8048316:       69 c0 cd cc cc cc       imul   $0xcccccccd,%eax,%eax
 804831c:       d1 f8                   sar    %eax
 804831e:       5d                      pop    %ebp
 804831f:       c3                      ret    

08048320 <divide10>:
 8048320:       55                      push   %ebp
 8048321:       89 e5                   mov    %esp,%ebp
 8048323:       8b 4d 08                mov    0x8(%ebp),%ecx
 8048326:       89 c8                   mov    %ecx,%eax
 8048328:       ba 67 66 66 66          mov    $0x66666667,%edx
 804832d:       f7 ea                   imul   %edx
 804832f:       89 c8                   mov    %ecx,%eax
 8048331:       c1 f8 1f                sar    $0x1f,%eax
 8048334:       c1 fa 02                sar    $0x2,%edx
 8048337:       29 c2                   sub    %eax,%edx
 8048339:       89 d0                   mov    %edx,%eax
 804833b:       5d                      pop    %ebp
 804833c:       c3                      ret    
 804833d:       8d 76 00                lea    0x0(%esi),%esi

08048340 <divide>:
 8048340:       55                      push   %ebp
 8048341:       89 e5                   mov    %esp,%ebp
 8048343:       8b 45 08                mov    0x8(%ebp),%eax
 8048346:       99                      cltd   
 8048347:       f7 7d 0c                idivl  0xc(%ebp)
 804834a:       5d                      pop    %ebp
 804834b:       c3                      ret    
 804834c:       8d 74 26 00             lea    0x0(%esi,1),%esi
Re[6]: Как Реализовать atoi без стандартных библиотек
От: alnsn Великобритания http://nasonov.blogspot.com
Дата: 03.11.04 10:58
Оценка:
A>$ objdump -s a.out
тут описка
$ objdump -d a.out
Re[6]: Как Реализовать atoi без стандартных библиотек
От: MaximE Великобритания  
Дата: 03.11.04 11:01
Оценка:
On Wed, 03 Nov 2004 10:55:37 GMT, alnsn <21403@news.rsdn.ru> wrote:

> ME>Я хочу узнать действительно ли умножение быстрее деления? Если бы это было сложение и сдвиг, то да, но вот умножение вместо деления..

>
>

> 08048320 <divide10>:
>  8048320:       55                      push   %ebp
>  8048321:       89 e5                   mov    %esp,%ebp
>  8048323:       8b 4d 08                mov    0x8(%ebp),%ecx
>  8048326:       89 c8                   mov    %ecx,%eax
>  8048328:       ba 67 66 66 66          mov    $0x66666667,%edx
>  804832d:       f7 ea                   imul   %edx
>  804832f:       89 c8                   mov    %ecx,%eax
>  8048331:       c1 f8 1f                sar    $0x1f,%eax
>  8048334:       c1 fa 02                sar    $0x2,%edx
>  8048337:       29 c2                   sub    %eax,%edx
>  8048339:       89 d0                   mov    %edx,%eax
>  804833b:       5d                      pop    %ebp
>  804833c:       c3                      ret
>  804833d:       8d 76 00                lea    0x0(%esi),%esi
>


Мораль: хватит баловаться с битами, за вас уже давно все продумали

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.