FindChar

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Leo
Beiträge: 420
Registriert: 26.10.2004 18:26

FindChar

Beitrag von Leo »

Ich hab ne Procedure geschrieben um einen
einzigen Buchstaben in einem String zu suchen.
PB's FindString scheint jedoch schneller als
mein FindChar zu sein

Code: Alles auswählen

Procedure FindChar(*string.BYTE,asc.l,lenstr)
    start = *string 
    Repeat
        If *string\b = asc
            ProcedureReturn *string - start + 1
        EndIf
        *string + 1
    Until *string\b = 0
EndProcedure

#N = 1000000
string.s = "searchinmeeeeeeee3"
tofind.s = "3"
asctofind.l = Asc(tofind)
len.l = Len(string)
ptr.l = @string

Time1 = GetTickCount_()
For I = 0 To #N
    FindChar(ptr,asctofind,len)
Next
Time1 = GetTickCount_() - Time1

Time2 = GetTickCount_()
For I = 0 To #N
    FindString(string,tofind,0)
Next
Time2 = GetTickCount_() - Time2 

strOut.s = "FindChar: "+Str(Time1)+#CRLF$
strOut.s = strOut.s + "FindString: "+Str(Time2)
MessageRequester("Ergebnis",strOut)
Weiß jemand, wie man das noch optimieren könnte?
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich habe mal deinen 3. Parameter rausgenommen. Den hast du ja sowieso nicht gebraucht. Leider hat das nicht viel geändert. Womöglich ist die Funktion [c]FindString()[/c] aus PureBasic in ASM optimiert oder sowas.

Code: Alles auswählen

Procedure FindChar(*string.BYTE, asc.l)
  start = *string
  While *string\b
    If *string\b = asc
      ProcedureReturn *string - start + 1
    EndIf
    *string + 1
  Wend
EndProcedure

#N = 1000000
String.s = "searchinmeeeeeeee3123456123cb1g2348cbnq0webftrqc0n9qwbet691bt4  qböoäöa-asbe0rß1bv634r660qlbdf-asubdpfz10735646vrzpawbwöehbf76v6r9b3807b1p9sbaösejhbfquiowebz7r81bvg5340brqpweöfjkqböwev qöwjerh 1092346r18 4rpuqwzefqhw7e1 34nr7q0 w8 eh7r0q whe7qf0 wnejöasdjfh0q93478zbr1093br4höaowuez f0q7wez0fr13j4u rhqw7e rfqwe7rq0w9e rqh3 er13 4rqpweör v#"
tofind.s = "#"
asctofind.l = Asc(tofind)
len.l = Len(String)
ptr.l = @String

Time1 = GetTickCount_()
  For I = 0 To #N
    FindChar(ptr, asctofind)
  Next
Time1 = GetTickCount_() - Time1

Time2 = GetTickCount_()
  For I = 0 To #N
    FindString(String, tofind, 0)
  Next
Time2 = GetTickCount_() - Time2

strOut.s = "FindChar: " + Str(Time1) + #CRLF$
strOut.s = strOut.s + "FindString: " + Str(Time2)
MessageRequester("Ergebnis", strOut)
Leo
Beiträge: 420
Registriert: 26.10.2004 18:26

Beitrag von Leo »

Oops! Hatte das vorher mit einer For/Next Schleife gemacht,
deswegen der 3. Parameter...
Ich probier schon die ganze Zeit, da irgendwas mit ASM
zu machen, komme aber nicht weit..

Ich weiß nämlich nicht, wie ich mit InlineAssembler auf *string
zugreifen kann
[c]!MOV eax,dword[v_*string][/c] scheint ja nicht zu gehen..
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

ist ja auch n byte...
Bild
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

probier mal p_string ;) geht vielleicht beim inline ASM(ohne das ! am anfang).
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Leo
Beiträge: 420
Registriert: 26.10.2004 18:26

Beitrag von Leo »

MVXA hat geschrieben:ist ja auch n byte...
Nein, ist es nicht
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Wie wärs damit:

Code: Alles auswählen

Procedure FindChar(*string.BYTE, asc.l) 
  ;start = *string
  
  MOV eax, *string   ;Pointer auf String in eax
  MOV ebx, asc       ;Ascii-code von Zeichen in ebx, genauer bl
  startpunkt:
  CMP byte[eax], 0   ;überprüfen, ob Stringende
  JZ  l_notfound     ;wenn ja, return 0!
  
  CMP byte[eax], bl  ;überprüfen, ob gefunden
  JE l_jump          ;wenn ja, dann aus schleife raus
  
  INC eax            ;Stringpointer erhöhen
  JMP l_startpunkt   ;zum Schleifenstart springen
  jump:              ;Ende der Schleife
  
  
  SUB eax, *string   ;Pointer subtrahieren, um Pos. zu bekommen
  INC eax            ;Position von _1_ bis x
  ProcedureReturn
  
  notfound:          ;wenn nicht gefunden
  ProcedureReturn 0
  
  ; While *string\b
  ; If *string\b = asc 
  ; ProcedureReturn *string - start + 1 
  ; EndIf 
  ; *string + 1 
  ; Wend 
EndProcedure 


#N = 900000 
String.s = "searchinmeeeeeeee3123456123cb1g2348cbnq0webftrqc0n9qwbet691bt4  qböoäöa-asbe0rß1bv634r660qlbdf-asubdpfz10735646vrzpawbwöehbf76v6r9b3807b1p9sbaösejhbfquiowebz7r81bvg5340brqpweöfjkqböwev qöwjerh 1092346r18 4rpuqwzefqhw7e1 34nr7q0 w8 eh7r0q whe7qf0 wnejöasdjfh0q93478zbr1093br4höaowuez f0q7wez0fr13j4u rhqw7e rfqwe7rq0w9e rqh3 er13 4rqpweör v#" 
tofind.s = "#" 
asctofind.l = Asc(tofind) 
ptr.l = @String 


Delay(1000) 

Time1 = GetTickCount_() 
For I = 0 To #N 
  FindChar(ptr, asctofind) 
Next 
Time1 = GetTickCount_() - Time1 

Time2 = GetTickCount_() 
For I = 0 To #N 
  FindString(String, tofind, 0) 
Next 
Time2 = GetTickCount_() - Time2 

strOut.s = "FindChar: " + Str(Time1) + #CRLF$ 
strOut.s = strOut.s + "FindString: " + Str(Time2) 
MessageRequester("Ergebnis", strOut)
Weiss nicht obs am optimalsten ist oder obs vollständig stimmt, aber..

cu
Remi :wink:
Zuletzt geändert von remi_meier am 19.03.2005 18:47, insgesamt 4-mal geändert.
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

hab nur auf mov und dword geschaut. ich hab gedacht du fragst dort den string direkt ab. ist ja auch egal.... <_<
Bild
Leo
Beiträge: 420
Registriert: 26.10.2004 18:26

Beitrag von Leo »

Cool! Ich versteh sogar fast alles :)

Nur was sind JZ (Könnte JumpZero heißen, würde sogar passen) und bl?
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

JZ = JumpIfZero könnte auch JE sein (JumpIfEqual)
bl = LowByte of Ebx-Register

Aber ich bin mir mit dem InlineAsm nicht mehr so sicher..
Vielleicht verschieb ich da ein bisschen was falsches, ich überprüfs mal

cu
Remi
Antworten