Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Binärdarstellung einer Zahl mit einer einzigen Stringallokation (https://www.delphipraxis.net/168484-binaerdarstellung-einer-zahl-mit-einer-einzigen-stringallokation.html)

Amateurprofi 26. Mai 2012 19:22

AW: Binärdarstellung einer Zahl mit einer einzigen Stringallokation
 
Zitat:

Zitat von himitsu (Beitrag 1167940)
Wegen Speicher ... macht es doch so wie IntToStr oder Format?

ein
Delphi-Quellcode:
array[0..31] of Char
als Puffer auf'm Stack,
dann einmal die Zeichen berechnen und den Puffer befüllen,
gleichzeitig werden die Bits automatisch gezählt
und zum Schluß ein SetString, wo nur einmal Speicher allociert wird.
:stupid:

Wirklich schnell ist das aber auch nicht.
Warum?:
Man schreibt die Daten in den Puffer und das SetStr kopiert sie dann in den String.
Besser ist, die Länge des Strings zu definieren und dann direkt in den String zu schreiben.

Die beiden nachstehenden Routinen machen das alles recht flink.
Die zweite Routine ist deutlich schneller weil bummelige Shifts vermieden werden und weil vorwärts geschrieben wird.
Die Tabelle zeigt für die Werte 0, 2^0..31 von links nach rechts
- den Wert
- benötigte CPU-Takte für gammatesters Routine (#11)
- dto für meine Routine (#9)
- dto für die erste der untenstehenden Routinen
- dto für die zweite der untenstehenden Routinen

Code:
         0 238 110 126 126
         1 578 110 126 136
         2 476 136 136 126
         4 526 162 144 144
         8 500 186 144 144
        16 502 212 152 144
        32 510 238 160 152
        64 518 262 162 160
       128 526 288 162 160
       256 534 322 170 170
       512 544 340 178 170
      1024 552 364 204 178
      2048 570 390 194 178
      4096 586 408 196 186
      8192 594 442 212 186
     16384 604 466 212 194
     32768 620 484 220 188
     65536 628 518 228 204
    131072 630 536 230 204
    262144 646 562 238 204
    524288 730 646 246 204
   1048576 738 672 246 204
   2097152 740 704 272 212
   4194304 756 722 262 220
   8388608 782 756 272 220
  16777216 790 790 288 228
  33554432 806 798 280 228
  67108864 806 824 296 228
 134217728 832 850 296 238
 268435456 850 892 314 246
 536870912 884 900 306 246
1073741824 892 926 314 254
2147483648 908 952 322 254
Delphi-Quellcode:
FUNCTION IntToBin3(v:Cardinal):string;
asm
            push ebx
            push eax                       // V
            push edx                       // @Result
            // Benötigte Länge in EBX
            xor  ebx,ebx
            bsr  ebx,eax                   // Länge-1
            lea  ebx,[ebx+1]               // Länge
            // Result löschen
            mov  eax,edx
            call System.@UStrClr
            // Kurzfassung von NewUniCodeString
            lea  eax,[ebx*2+12+2]          // Länge*2 + SizeOf(StrRec) + 2
            call System.@GetMem
            mov  edx,DefaultUnicodeCodePage
            and  edx,$FFFF                 // nur LoWord
            or   edx,$20000                 // elemSize
            mov  [eax],edx                 // StrRec.codePage und .elemSize
            mov  [eax+4],1                  // StrRec.refCnt
            mov  [eax+8],ebx               // StrRec.Length
            lea  eax,[eax+12]              // @NewString
            // @NewString in Result stellen
            pop  edx
            mov  [edx],eax                 // Result
            // Ende 00 ans Stringende schreiben
            lea  eax,[eax+ebx*2]           // @NewString[Len+1]
            mov  word [eax],0               // Str-Terminator
            // V als Binärstring in Result schreiben
            pop  edx                       // V
@Loop:     lea  eax,[eax-2]
            shr  edx,1
            setc bl
            lea  ebx,[ebx+$30]
            mov  [eax],bx
            jne  @Loop
            pop  ebx
end;
Delphi-Quellcode:
FUNCTION IntToBin4(v:Cardinal):string;
asm
            push ebx
            push eax                       // V
            push edx                       // @Result
            // Benötigte Länge in EBX
            xor  ebx,ebx
            bsr  ebx,eax                   // Länge-1
            lea  ebx,[ebx+1]               // Länge
            // Result löschen
            mov  eax,edx
            call System.@UStrClr
            // Kurzfassung von NewUniCodeString
            lea  eax,[ebx*2+12+2]          // Länge*2 + SizeOf(StrRec) + 2
            call System.@GetMem
            mov  edx,DefaultUnicodeCodePage
            and  edx,$FFFF                 // nur LoWord
            or   edx,$20000                 // elemSize
            mov  [eax],edx                 // StrRec.codePage und .elemSize
            mov  [eax+4],1                  // StrRec.refCnt
            mov  [eax+8],ebx               // StrRec.Length
            lea  eax,[eax+12]              // @NewString
            mov  word[eax+ebx*2],0          // Str-Terminator
            // @NewString in Result stellen
            pop  edx
            mov  [edx],eax                 // Result
            // V als Binärstring in Result schreiben
            pop  edx                       // V
            lea  eax,[eax+ebx*2]           // Hinter String
            neg  ebx
            lea  ecx,[ebx+32]              // ( v so nach links verschieben,
            shl  edx,cl                    //   Nit 31 steht )
            jmp  @Entry
@Loop:     add  edx,edx
@Entry:    sets cl                        // Sign Flag in BL
            lea  ecx,[ecx+$30]             // in Char wandeln
            mov  [eax+ebx*2],cx            // Char ib String schreiben
            add  ebx,1
            jne  @Loop                     // weiter bis edx leer ist
            pop  ebx
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:29 Uhr.
Seite 3 von 3     123   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz