int in String umwandeln....



  • Wenn es nur um Geschwindigkeit geht, dann kannst du ja gleich bei itoa bleiben, dann ist die Frage ja aufgrund deiner Messergebnisse überflüssig. 🙄

    Vielleicht eher im assembler-Forum nachfragen.



  • Kannst es noch mit multiplikationen ausprobieren.

    int len = 1, b=system;
    while ( num >= b ) {
       b *= base; len++;
    }
    

    Ist ca 6x schneller.
    Kurt



  • wie wäre es mit man: sprintf(3)?



  • supertux schrieb:

    wie wäre es mit man: sprintf(3)?

    Wie geht das zb mit basis 12 ? 😉
    Kurt



  • Ja, die multiplikation ist wirklich ein gutes stück schneller aber leider immer noch um einiges langsamer als die kopier variante. es ergeben sich auch ein paar Probleme bei der Multiplikationsvariante...

    printf ist ja allgemein mehr für flexibilität konstruiert als für performance. ich wüsste ehrlich gesagt auch nicht, wie ich damit ein beliebiges Zahlensystem als Basis verwenden lasse.

    Ich hab jetzt nochmal ne Variante mit optimierung für die Dualexponential Systeme. Bei diesen wandlungen mache ich die MS implementation von itoa ziemlich nass;)

    #define UINTTOSTRING_BUFSIZE				128
    
    #define UINTTOSTRING_ERROR_BUFFERTOSMALL	-1
    #define UINTTOSTRING_ERROR_SYSTEMOUTOFRANGE	-2
    
    #define UINTTOSTRING_USEFASTMODE
    
    const int UINTTOSTRING_DATATABLE[38][2] = {
    	0, 0x00000000, 0, 0x00000000, 1, 0x00000001, 0, 0x00000000,
    	2, 0x00000003, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000,
    	3, 0x00000007, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 
    	0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000,
    	4, 0x0000000F, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 
    	0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 
    	0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000,
    	0, 0x00000000, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000,
    	5, 0x0000001F, 0, 0x00000000, 0, 0x00000000, 0, 0x00000000,
    	0, 0x00000000, 0, 0x00000000
    };
    
    int UIntToString(unsigned int value, unsigned char system, char* poutput, size_t outputbufsize)
    {
      int stringsize;
      int part;
      char pbuffer[UINTTOSTRING_BUFSIZE];
      char* ppointer = pbuffer + UINTTOSTRING_BUFSIZE - 1;
    
      *ppointer = '\0';
    
      if (system<2 || system>37) return UINTTOSTRING_ERROR_SYSTEMOUTOFRANGE;
    
    #ifdef UINTTOSTRING_USEFASTMODE
      if (UINTTOSTRING_DATATABLE[system][0])
      {
        unsigned int bitcount = UINTTOSTRING_DATATABLE[system][0];
    	unsigned int bitmask = UINTTOSTRING_DATATABLE[system][1];
    
    	do {
    		ppointer--;
    		part = value & bitmask;
    		if (part>9) *ppointer = part - 10 + 'A';
    		else *ppointer = part + '0';
    		value>>= bitcount;
    	} while (value);
      }
      else
    #endif
      {
    	do {
    		ppointer--;
    		part = value % system;
    		if (part>9) *ppointer = part - 10 + 'A';
    		else *ppointer = part + '0';
    		value/= system;
    	} while (value);
      }
    
      stringsize = pbuffer + UINTTOSTRING_BUFSIZE - ppointer;
      if (outputbufsize < stringsize) return UINTTOSTRING_ERROR_BUFFERTOSMALL;
    
      strcpy(poutput, ppointer);
      return stringsize-1;
    }
    

    braucht für die Zahl 0xF3BBCA95 bei 1000 durchläufen:
    itoa -> ca. 270µs
    optimierte variante -> ca. 70µs

    Allerdings scheint der Overhead bei mir größer zu sein. Bei kleineren Wandlungen schrumpft der Vorsprung (50/30 bei nur einer Stelle...)

    Ich glaub ich hab da eh schon viel zu viel Zeit rein investiert. Manchmal verbeis ich mich etwas mit dieser blöden optimiererei...



  • Wahrscheinlich würde es noch ganzes Stück schneller wenn du folgendes machst

    const char * parttable = "0123456789ABCDEF";
        do {
            ppointer--;
            *ppointer = parttable[value % system];
            value/= system;
        } while (value);
    

    Kurt



  • He, die Idee war nicht schlecht. Damit komme ich nun auch bei der langsamen Variante mit itoa schon fasst auf Augenhöhe;)

    Ich hab auch nochmal geschaut, wieviel ich mir maximal sparen könnte, wenn ich den Puffer weg lasse. Das würde beim oben genannten Benchmark nur nochmal 20µs sparen (gut, bei der schnellen Variante wäre das doch schon ein netter Anteil.



  • ZuK schrieb:

    Solange system nicht negativ und > 0 ist ist die Stellenanzahl des Ergebnisses in deinem Fall (für unsigned int ) immer
    ( value / system ) + 1
    Kurt

    nein aber logsystem(value)+1log_{system}(value)+1



  • Ich hab mich dann aber korrigiert. Bin dann auch auf deine Formel gekommen. Das berechnen von logsystem(value)log_{system}(value) mit den mitteln der c math-lib war mir dann aber doch zu mühsam. ( Ich weiss zwar dass es irgendwie geht, meine Mathematikkentnisse haben aber in den letzten 25 Jahren schwer nachgelassen ) 🙂
    Kurt



  • $log_{system}(value) = \frac{log(value)}{log(system)}$

    der geschwindigkeitshit ist das natürlich auch nicht, aber wollte es nur mal angemerkt haben 😉


Anmelden zum Antworten