Select-en von Zahlen vs Strings

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

Florian

Betreff: Select-en von Zahlen vs Strings

BeitragDo, März 16, 2006 22:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier ein beispiel einer VM Stackmaschine.


Geschrieben mit PowerBasic

Code: [AUSKLAPPEN]


%True  = -1
%False = Not %True
%Debug = %False

%Push =  1
%Pop  =  2
%dbl  =  3
%Swap =  4

%Mul  =  5
%Div  =  6
%Add  =  7
%Sub  =  8
%Neg  =  9
%Incr = 10
%Decr = 11

%Not  = 12
%And  = 13
%Or   = 14
%Xor  = 15

%Call = 16
%Ret  = 17
%Jmp  = 18
%Jle  = 19

%Stor = 20
%Load = 21

%In   = 22
%Out  = 23

%MaxCode        = 4096
%MaxData        = 4096
%MaxStack       = 4096
%MaxReturnStack = 1024

DIM CS(%MaxCode)        AS SHARED INTEGER
DIM DS(%MaxData)        AS SHARED INTEGER
DIM SS(%MaxStack)       AS SHARED INTEGER
DIM RS(%MaxReturnStack) AS SHARED INTEGER

DIM IP AS SHARED INTEGER
DIM SP AS SHARED INTEGER
DIM RP AS SHARED INTEGER



'CS(0)=%PUSH
'CS(1)=10
'CS(2)=%PUSH
'CS(3)=12
'CS(4)=%Add
'CS(5)=%Out
'CS(6)=%In
'CALL SAVEVM("VM.DAT")
'CALL DecodeMEM ("VM.TXT")
CALL LOADVMBIN("VM.BIN")
CALL RUNVM

FUNCTION LOADVM(Dateiname AS STRING)
 DIM Dateizusatz AS STRING
 Dateizusatz$=UCASE$(MID$(Dateiname$,Instr(Dateiname$,".")+1))
 SELECT CASE Dateizusatz$
  CASE "BIN",""
   LOADVMBIN Dateiname$
  CASE ELSE
   LOADVMASC Dateiname$
 END SELECT
END FUNCTION

FUNCTION SAVEVM(Dateiname AS STRING)
 DIM Dateizusatz AS STRING
 Dateizusatz$=UCASE$(MID$(Dateiname$,Instr(Dateiname$,".")+1))
 SELECT CASE Dateizusatz$
  CASE "BIN",""
   SAVEVMBIN Dateiname$
  CASE ELSE
   SAVEVMASC Dateiname$
 END SELECT
END FUNCTION

FUNCTION BefehlName$(BefehlNr AS INTEGER)
 SELECT CASE BefehlNr
  CASE %Push
   FUNCTION= "Push"

  CASE %Pop
   FUNCTION= "Pop"

  CASE %dbl
   FUNCTION= "dbl"

  CASE %Swap
   FUNCTION= "Swap"

  CASE %Mul
   FUNCTION= "Mul"

  CASE %Div
   FUNCTION= "Div"

  CASE %Add
   FUNCTION= "Add"

  CASE %Sub
   FUNCTION= "Sub"

  CASE %Neg
   FUNCTION= "Neg"

  CASE %Incr
   FUNCTION= "Incr"

  CASE %Decr
   FUNCTION= "Decr"

  CASE %Not
   FUNCTION= "Not"

  CASE %And
   FUNCTION= "And"

  CASE %Or
   FUNCTION= "Or"

  CASE %Xor
   FUNCTION= "Xor"

  CASE %Call
   FUNCTION= "Call"

  CASE %Ret
   FUNCTION= "Ret"

  CASE %Jmp
   FUNCTION= "Jmp"

  CASE %Jle
   FUNCTION= "Jle"

  CASE %Stor
   FUNCTION="Stor"

  CASE %Load
   FUNCTION="Load"

  CASE %In
   FUNCTION="In"

  CASE %Out
   FUNCTION="Out"

 END SELECT
END FUNCTION

FUNCTION DecodeMEM(Dateiname AS STRING)
 DIM DateiNr AS INTEGER
 DIM Zeiger  AS INTEGER
 DIM Befehl  AS STRING

 DateiNr=FREEFILE
 OPEN Dateiname$ FOR OUTPUT AS DateiNr

 FOR Zeiger=0 TO %MaxCode
  SELECT CASE CS(Zeiger)
   CASE %Push
    INCR Zeiger
    Befehl$= "Push"+STR$(CS(Zeiger))

   CASE %Pop
    Befehl$= "Pop"

   CASE %dbl
    Befehl$= "dbl"

   CASE %Swap
    Befehl$= "Swap"

   CASE %Mul
    Befehl$= "Mul"

   CASE %Div
    Befehl$= "Div"

   CASE %Add
    Befehl$= "Add"

   CASE %Sub
    Befehl$= "Sub"

   CASE %Neg
    Befehl$= "Neg"

   CASE %Incr
    Befehl$= "Incr"

   CASE %Decr
    Befehl$= "Decr"

   CASE %Not
    Befehl$= "Not"

   CASE %And
    Befehl$= "And"

   CASE %Or
    Befehl$= "Or"

   CASE %Xor
    Befehl$= "Xor"

   CASE %Call
    INCR Zeiger
    Befehl$= "Call"+STR$(CS(Zeiger))

   CASE %Ret
    Befehl$= "Ret"

   CASE %Jmp
    INCR Zeiger
    Befehl$= "Jmp"+STR$(CS(Zeiger))

   CASE %Jle
    INCR Zeiger
    Befehl$= "Jle"+STR$(CS(Zeiger))

   CASE %Stor
    INCR Zeiger
    Befehl$="Stor"+STR$(CS(Zeiger))

   CASE %Load
    INCR Zeiger
    Befehl$="Load"+STR$(CS(Zeiger))

   CASE %In
    Befehl$="In"

   CASE %Out
    Befehl$="Out"

   CASE ELSE
    Befehl$="Nop"

  END SELECT
  PRINT #DateiNr,Befehl$
 NEXT

 CLOSE DateiNr
END FUNCTION

SUB SAVEVMBIN(Dateiname AS STRING)
 DIM DateiNr AS INTEGER
 DIM Zeiger  AS INTEGER

 DateiNr=FREEFILE
 OPEN Dateiname$ FOR BINARY AS DateiNr

 PUT$ #DateiNr, MKI$(%MaxCode)
 PUT$ #DateiNr, MKI$(%MaxData)
 PUT$ #DateiNr, MKI$(%MaxStack)
 PUT$ #DateiNr, MKI$(%MaxReturnStack)

 PUT$ #DateiNr, MKI$(IP)
 PUT$ #DateiNr, MKI$(SP)
 PUT$ #DateiNr, MKI$(RP)

 'Code speichern
 FOR Zeiger% = 0 TO %MaxCode
  PUT$ #DateiNr,MKI$(CS(Zeiger%))
 NEXT

 'Daten speichern
 FOR Zeiger% = 0 TO %MaxData
  PUT$ #DateiNr,MKI$(DS(Zeiger%))
 NEXT

 'Stack speichern
 FOR Zeiger% = 0 TO %MaxStack
  PUT$ #DateiNr,MKI$(SS(Zeiger%))
 NEXT

 'MaxReturnStack speichern
 FOR Zeiger% = 0 TO %MaxReturnStack
  PUT$ #DateiNr,MKI$(RS(Zeiger%))
 NEXT

 CLOSE DateiNr
END SUB

SUB LOADVMBIN(Dateiname AS STRING)
 DIM DateiNr AS INTEGER

 DIM MinCodeS        AS STRING
 DIM MinDataS        As STRING
 DIM MinStackS       AS STRING
 DIM MinReturnStackS AS STRING

 DIM MinCode         AS INTEGER
 DIM MinData         As INTEGER
 DIM MinStack        AS INTEGER
 DIM MinReturnStack  AS INTEGER

 DIM IPS AS STRING
 DIM SPS AS STRING
 DIM RPS AS STRING
 DIM Zeiger AS INTEGER

 DIM CodeS        AS STRING
 DIM DataS        AS STRING
 DIM StackS       AS STRING
 DIM ReturnStackS AS STRING

 DateiNr=FREEFILE
 OPEN Dateiname$ FOR BINARY AS DateiNr

 GET$ #DateiNr,2,MinCodeS$
 GET$ #DateiNr,2,MinDataS$
 GET$ #DateiNr,2,MinStackS$
 GET$ #DateiNr,2,MinReturnStackS$

 MinCode%=CVI(MinCodeS$)
 MinData%=CVI(MinDataS$)
 MinStack%=CVI(MinStackS$)
 MinReturnStack%=CVI(MinReturnStackS$)

 IF MinCode%>%MaxCode OR MinData%>%MaxData OR _
    MinStack%>%MaxStack OR MinReturnStack%>%MaxReturnStack THEN

  CLOSE DateiNr
 END IF

 GET$ #DateiNr, 2, IPS$
 GET$ #DateiNr, 2, SPS$
 GET$ #DateiNr, 2, RPS$

 IP=CVI(IPS$)
 SP=CVI(SPS$)
 RP=CVI(RPS$)

 'Code einlesen
 FOR Zeiger=0 TO MinCode%
  GET$ #DateiNr, 2, CodeS$
  CS(Zeiger)=CVI(CodeS$)
 NEXT

 'Daten einlesen
 FOR Zeiger=0 TO MinData%
  GET$ #DateiNr, 2, DataS$
  DS(Zeiger)=CVI(DataS$)
 NEXT

 'Stack einlesen
 FOR Zeiger=0 TO MinStack%
  GET$ #DateiNr, 2, StackS$
  SS(Zeiger)=CVI(StackS$)
 NEXT

 'Returnstack einlesen
 FOR Zeiger=0 TO MinReturnStack%
  GET$ #DateiNr, 2, ReturnStackS$
  RS(Zeiger)=CVI(ReturnStackS$)
 NEXT

 Close DateiNr
END SUB

SUB SAVEVMASC(Dateiname AS STRING)
 DIM DateiNr AS INTEGER
 DIM Zeiger  AS INTEGER

 DateiNr=FREEFILE
 OPEN Dateiname$ FOR OUTPUT AS DateiNr

'Informatioen ?ber sie Segmente der VM speichern
 PRINT #DateiNr, %MaxCode
 PRINT #DateiNr, %MaxData
 PRINT #DateiNr, %MaxStack
 PRINT #DateiNr, %MaxReturnStack

'Position der Zeiger speichern

 PRINT #DateiNr, IP
 PRINT #DateiNr, SP
 PRINT #DateiNr, RP

 'Code speichern
 FOR Zeiger% = 0 TO %MaxCode
  PRINT #DateiNr,CS(Zeiger%)
 NEXT

 'Daten speichern
 FOR Zeiger% = 0 TO %MaxData
  PRINT #DateiNr,DS(Zeiger%)
 NEXT

 'Stack speichern
 FOR Zeiger% = 0 TO %MaxStack
  PRINT #DateiNr,SS(Zeiger%)
 NEXT

 'MaxReturnStack speichern
 FOR Zeiger% = 0 TO %MaxReturnStack
  PRINT #DateiNr,RS(Zeiger%)
 NEXT

 CLOSE DateiNr
END SUB

SUB INSTVM()
 DIM ZEIGER AS INTEGER

 IP=0
 SP=0
 RP=0

 FOR Zeiger=0 TO %MaxCode
  CS(Zeiger)=0
 NEXT

 FOR Zeiger=0 TO %MaxData
  DS(Zeiger)=0
 NEXT

 FOR Zeiger=0 TO %MaxStack
  SS(Zeiger)=0
 NEXT

 FOR Zeiger=0 TO %MaxReturnStack
  RS(Zeiger)=0
 NEXT
END SUB

SUB LOADVMASC(Dateiname AS STRING)
 DIM DateiNr AS INTEGER

 DIM MinCodeS        AS STRING
 DIM MinDataS        As STRING
 DIM MinStackS       AS STRING
 DIM MinReturnStackS AS STRING

 DIM MinCode         AS INTEGER
 DIM MinData         As INTEGER
 DIM MinStack        AS INTEGER
 DIM MinReturnStack  AS INTEGER

 DIM IPS AS STRING
 DIM SPS AS STRING
 DIM RPS AS STRING
 DIM Zeiger AS INTEGER

 DIM CodeS        AS STRING
 DIM DataS        AS STRING
 DIM StackS       AS STRING
 DIM ReturnStackS AS STRING

 DateiNr=FREEFILE
 OPEN Dateiname$ FOR INPUT AS DateiNr

 LINE INPUT# DateiNr,MinCodeS$
 LINE INPUT# DateiNr,MinDataS$
 LINE INPUT# DateiNr,MinStackS$
 LINE INPUT# DateiNr,MinReturnStackS$

 MinCode%=VAL(MinCodeS$)
 MinData%=VAL(MinDataS$)
 MinStack%=VAL(MinStackS$)
 MinReturnStack%=VAL(MinReturnStackS$)

 IF MinCode%>%MaxCode OR MinData%>%MaxData OR _
    MinStack%>%MaxStack OR MinReturnStack%>%MaxReturnStack THEN

  CLOSE DateiNr
 END IF

 LINE INPUT #DateiNr, IPS$
 LINE INPUT #DateiNr, SPS$
 LINE INPUT #DateiNr, RPS$

 IP=VAL(IPS$)
 SP=VAL(SPS$)
 RP=VAL(RPS$)

 'Code einlesen
 FOR Zeiger=0 TO MinCode%
  LINE INPUT #DateiNr, CodeS$
  CS(Zeiger)=VAL(CodeS$)
 NEXT

 'Daten einlesen
 FOR Zeiger=0 TO MinData%
  LINE INPUT #DateiNr, DataS$
  DS(Zeiger)=VAL(DataS$)
 NEXT

 'Stack einlesen
 FOR Zeiger=0 TO MinStack%
  LINE INPUT #DateiNr, StackS$
  SS(Zeiger)=VAL(StackS$)
 NEXT

 'Returnstack einlesen
 FOR Zeiger=0 TO MinReturnStack%
  LINE INPUT #DateiNr, ReturnStackS$
  RS(Zeiger)=VAL(ReturnStackS$)
 NEXT

 CLOSE DateiNr
END SUB

SUB RUNVM()
 CLS
 DO

  $IF %DEBUG
  PRINT BefehlName$(CS(IP))
  $ENDIF

  SELECT CASE CS(IP)
   CASE %Push
    SS(SP)=CS(IP+1)
    INCR SP
    INCR IP,2

   CASE %Pop
    DECR SP
    INCR IP

   CASE %dbl
    SS(SP)=SS(SP-1)
    INCR SP
    INCR IP

   CASE %Swap
    SWAP SS(SP-1),SS(SP-2)
    INCR IP

   CASE %Mul
    SS(SP-2)=SS(SP-1)*SS(SP-2)
    DECR SP
    INCR IP

   CASE %Div
    SS(SP-2)=SS(SP-1)/SS(SP-2)
    DECR SP
    INCR IP

   CASE %Add
    INCR SS(SP-2),SS(SP-1)
    DECR SP
    INCR IP

   CASE %Sub
    DECR SS(SP-2),SS(SP-1)
    DECR SP
    INCR IP

   CASE %NEG
    SS(SP-1)= -SS(SP-1)
    INCR IP

   CASE %Not
    SS(SP-1)=NOT SS(SP-1)
    INCR IP

   CASE %And
    SS(SP-2)=SS(SP-1) AND SS(SP-2)
    DECR SP
    INCR IP

   CASE %Or
    SS(SP-2)=SS(SP-1) OR SS(SP-2)
    DECR SP
    INCR IP

   CASE %Xor
    SS(SP-2)=SS(SP-1) XOR SS(SP-2)
    DECR SP
    INCR IP

   CASE %Incr
    INCR SS(SP-1)
    INCR IP

   CASE %Decr
    DECR SS(SP-1)
    INCR IP

   CASE %Call
    RS(RP)=IP+2
    INCR RP
    IP=CS(IP+1)

   CASE %Ret
    DECR RP
    IP=RS(RP)

   CASE %Jmp
    IP=CS(IP+1)

   CASE %Jle
    IF SS(SP-1)=<0 THEN
     IP=CS(IP+1)
    ELSE
     INCR IP,2
    END IF

   CASE %Stor
    DS(CS(IP+1))=SS(SP-1)
    DECR SP
    INCR IP,2

   CASE %Load
    INCR SP
    SS(SP)=DS(CS(IP+1))
    INCR IP,2

   CASE %In
    END
   CASE %Out
    PRINT SS(SP-1)
    INCR IP
   CASE ELSE
    INCR IP
  END SELECT
 LOOP
END SUB

Das große BlitzBasic Community Tutorial
Stackmaschine 2.0
 

ke^kx

BeitragDo, März 16, 2006 22:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist es so viel schneller das ganze mit IntegerVars zu machen als mit Strings? Ich Schreib nämlich selbst gerade an einem Interpreter (oder wie auch immer man das richtig nennt Wink ) und mir wurde gesagt, dass das bei 1000 durchgegangenen Befehlen nur ca. 0.1 Millisekunde ausmacht. In der OH heißt es aber das String die langsamsten Variablen seinen (was ja auch logisch ist). Wie groß ist denn nun der Unterschied?

Jiriki
http://i3u8.blogspot.com
Asus Striker II
Intel Core2Quad Q9300 @ 2,5 GHz (aber nur zwei Kerne aktiv aufgrund der Instabilität -.-)
Geforce 9800 GTX
2GB RAM
 

Dreamora

BeitragDo, März 16, 2006 22:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Strings sind nicht umbedingt langsam, das hängt von ihrer Länge ab. Ein Int ist halt immer 4 Byte lang, während Strings keine feste Länge haben, weswegen dort entsprechende Tests länger oder kürzer werden können. Auch können sie nicht so hoch optimiert werden, wie mit Zahlen, eben wegen diesem variablen Verhalten.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

ke^kx

BeitragDo, März 16, 2006 23:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Das heißt wenn ich statt der Zahlen von 1 - 255 für 255 verschiedene Befehle immer 5 Zeichen lange Strings (machmal auch länger) benutze ist es deutlich langsamer? Oder bleibt der Unterschied trotzdem gering, obwohl die Strings 5 mal so lang sind?

Jiriki

[Edit]
Ok, ich hab es gerade mal ausprobiert:

Code: [AUSKLAPPEN]
timer = MilliSecs ()

a = "Hallo"

Select a

   Case "Hallo"
      
      Print "1"
      
   Case "Tschüss"
   
      Print "2"
      
End Select

Print MilliSecs () - timer


Beim einen Versuch habe ich es so ausgeführt -> braucht 21 Millisekunden
Beim anderen Versuch war a = 1 und die Select-Case Abfrage war 1 oder 2. -> 16 Millisekunden

Also macht es schon einen gewaltigen Unterschied. Oh, noch mal schnell testen wie groß der Unterschied ist, der durch das Umwandeln entsteht.

[Edit³]
Ok, es lohnt sich trotzdem: 18 Millisekunden trotz vorherigen Umwandeln -> 3 Millisekunden unterschied pro bearbeiteten String, wobei dies nur bei einem Schleifendurchlauf ist, mit jeder weitern Prüfung vergrößert sich der Abstand...
http://i3u8.blogspot.com
Asus Striker II
Intel Core2Quad Q9300 @ 2,5 GHz (aber nur zwei Kerne aktiv aufgrund der Instabilität -.-)
Geforce 9800 GTX
2GB RAM
 

Florian

BeitragDo, März 16, 2006 23:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Jiriki hat Folgendes geschrieben:
Ist es so viel schneller das ganze mit IntegerVars zu machen als mit Strings?
Jiriki


Test
IntegerVars und StringsVars

Code: [AUSKLAPPEN]

Zeit=MilliSecs()
For Z=1 To 20000
 S$=S$+1
Next
Print "Stringvariabeln: "+Str$(MilliSecs()-Zeit)

Zeit=MilliSecs()
For Z=1 To 20000
 Zahl=Zahl+1
Next
Zeit=MilliSecs()
Print "Integervariabeln: "+Str$(MilliSecs()-Zeit)

WaitKey


Jiriki hat Folgendes geschrieben:

Ich Schreib nämlich selbst gerade an einem Interpreter (oder wie auch immer man das richtig nennt :wink: ) und mir wurde gesagt, dass das bei 1000 durchgegangenen Befehlen nur ca. 0.1 Millisekunde ausmacht. In der OH heißt es aber das String die langsamsten Variablen seinen (was ja auch logisch ist). Wie groß ist denn nun der Unterschied?

Leiber ist dem nicht so.

Ich hatte mal einen Code Opimirer geschrieben bei den 1000 Befehlen ca. 200 Millisekunden dauern.
Das große BlitzBasic Community Tutorial
Stackmaschine 2.0
 

Dreamora

BeitragDo, März 16, 2006 23:30
Antworten mit Zitat
Benutzer-Profile anzeigen
~AUFSPALTUNG~

Hatte nicht mehr wirklich was mit dem Updater zu tun
Dreamora
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

ke^kx

BeitragFr, März 17, 2006 4:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Huiuiu, bei dir ist der Unterschied ja noch größer... Ich seh schon, dass es sich wirklich lohnt, auch wenn es aufwendiger ist.

@Dreamora:
Dankeschön Smile

Jiriki
http://i3u8.blogspot.com
Asus Striker II
Intel Core2Quad Q9300 @ 2,5 GHz (aber nur zwei Kerne aktiv aufgrund der Instabilität -.-)
Geforce 9800 GTX
2GB RAM
 

Dreamora

BeitragFr, März 17, 2006 5:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Aufwendiger ist es eigentlich nicht. Einfach Konstanten speichern mit den entsprechenden Namen und das wars Smile
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

ke^kx

BeitragFr, März 17, 2006 11:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, man kann halt die Parameter nicht mehr in Klammern hinter den Befehl schreiben, sondern muss einen Befehl festsetzen, der angiebt, wie viele Parameter dem Befehl folgen. Außerdem ist es ein Problem dass man ja häufig auch größere Zahlen als Integer-Werte angeben muss, dafür braucht man dann auch immer extra Befehle... Also ist schon etwas aufwendiger. Aber es lohnt sich ja Smile

Jiriki
http://i3u8.blogspot.com
Asus Striker II
Intel Core2Quad Q9300 @ 2,5 GHz (aber nur zwei Kerne aktiv aufgrund der Instabilität -.-)
Geforce 9800 GTX
2GB RAM

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group