Seite 1 von 1

3. StructureUnion und Euro in Cent umwandeln

Verfasst: 08.05.2008 21:54
von hjbremer
Hiermal ein weiteres kleines Beispiel mit StructureUnion

Unstrittig ist sicher das man mit Ganzzahlen schneller rechnen kann. Dazu muß man aber die Euro Beträge aus einer Liste in Cent umwandeln. Wir gehen davon aus, das die Beträge in der Liste maximal 2 Stellen haben.
Dafür gibt es eine sehr simple und einfache Methode siehe unten im Code die Procedure UsingCent(euro$).

Nur leider ist es nicht die schnellste Methode und bei etwas größeren Listen mit mehreren Einträgen pro Zeile, da zählt jeder Bruchteil einer Sekunde.
Die Procedure UsingCent2(*z.Zahlenformat1) ist bei mir 2-3 mal so schnell.

Es ist kaum zu glauben, erheblich mehr Code, aber schneller.

Code: Alles auswählen

;Vergleich von 2 Prozeduren die Euro Beträge die als String vorliegen in Cent umwandeln
;HJBremer Mai 2008

Structure Zahlenformat1
  StructureUnion
    s.s{15}  ;Größe des Fixstring von 15 individuell anpassen falls nötig
    c.c[0]
  EndStructureUnion
EndStructure    


Procedure UsingCent(euro$)  

   ;normaler Weg 

   ReplaceString(euro$,",",".",2)   ; komma durch punkt ersetzen im Original 
   wert=ValF(euro$)*100

ProcedureReturn wert

EndProcedure

Procedure UsingCent2(*z.Zahlenformat1)

;mit StructureUnion

Protected null  = '0'
Protected punkt = '.'
Protected komma = ','

Protected maxlg = SizeOf(Zahlenformat1) ;
Protected max   = maxlg - 1             ;warum maxlg-1, siehe PB Hilfe Strukturen
Protected j                             ;Schleifenvariable

;letztes Komma wird Punkt
If CountString(*z\s, ",")
   
   ;ersetzt *z\s = ReplaceString(*z\s, ",", ".") allerdings nur das letzte Komma 
   For j = max To 0 Step -1
      If *z\c[j] = komma
         *z\c[j] = punkt
         Break
      EndIf
   Next
 
EndIf
    
If CountString(*z\s, ".")

    ;wo ist der Punkt ?
    For j = 0 To max   
      If *z\c[j] = punkt
          ;Zahl mit Punkt ohne Kommastellen
          If *z\c[j+1] = 0  
             *z\c[j] = null
             *z\c[j+1] = null
          ;Zahl mit Punkt und 1 Kommastelle
          ElseIf *z\c[j+2] = 0  
             *z\c[j] = *z\c[j+1]
             *z\c[j+1] = null
          ;Zahl mit Punkt und 2 Kommastellen
          Else
             *z\c[j] = *z\c[j+1]
             *z\c[j+1] = *z\c[j+2]
             *z\c[j+2] = 0
          EndIf
          Break 
      EndIf
    Next
    
Else
    
    ;kein Punkt, 2 Nullen anhängen
    For j = 0 To max
        If *z\c[j] = 0
           *z\c[j] = null
           *z\c[j+1] = null
           Break
        EndIf
    Next
    
EndIf

ProcedureReturn Val(*z\s)

EndProcedure

;Demo=================================================

Debug UsingCent("123")
Debug UsingCent("123,")
Debug UsingCent("123,4")
Debug UsingCent("123,45")

Debug "---"

z.Zahlenformat1

z\s = "123"
Debug UsingCent2(z)

z\s = "123,"
Debug UsingCent2(z)

z\s = "123,4"
Debug UsingCent2(z)

z\s = "123,45"
Debug UsingCent2(z)

;Speedtest=Debugger ausschalten========================

max = 100000

a=GetTickCount_()

  For j = 1 To max
     
   euro$ = "123,45"
   cent = UsingCent(euro$)
   
  Next 

b=GetTickCount_()-a

a=GetTickCount_()

  For j = 1 To max
   
   z\s = "123,45"  
   cent2 = UsingCent2(z)
   
  Next 

c=GetTickCount_()-a


MessageRequester("",Str(cent)+"="+Str(b)+#LF$+Str(cent2)+"="+Str(c))
 

Verfasst: 08.05.2008 22:08
von NicTheQuick
Wieso nicht einfach das Komma mit 'RemoveString()' rauslöschen und dann mit 'Val()' zur Zahl machen?

Verfasst: 08.05.2008 22:22
von hjbremer
zwar schnell, aber nicht schnell genug und vor allem berücksichtigt nicht 123 oder 123, oder 123,0
Und noch unschöner, sollten die Beträge bereits einen Punkt haben, dann wird das nix mit VAL, VALF müßte es schon sein.

Dein Beispiel

Code: Alles auswählen

a=GetTickCount_()

  For j = 1 To max
    
    euro$ = "123,45"
    euro$ = RemoveString(euro$, "," , 1)
    cent3 = Val(euro$)

  Next

c=GetTickCount_()-a


MessageRequester("",Str(cent3)+"="+Str(c))

Verfasst: 16.05.2008 21:11
von hjbremer
kleine Erweiterung für jene, die mit 1/10 cent rechnen wollen.

Code: Alles auswählen

;Euro Beträge die als String vorliegen in Cent umwandeln
;HJBremer Mai 2008

Structure Zahlenformat1
  StructureUnion
    s.s{15}  ;Größe des Fixstring von 15 individuell anpassen falls nötig
    c.c[0]   ;ein Longwert kann nur 10 Stellen haben, sollte also reichen
  EndStructureUnion
  drei.c     ;falls man mit 1/10 Cent rechnen will
EndStructure    


Procedure UsingCent2(*z.Zahlenformat1)

;es wird eine Zahl erwartet, welche max 3 Kommastellen hat


Protected null  = '0'
Protected drei  = '3'
Protected punkt = '.'
Protected komma = ','
Protected char0 = ''

Protected maxlg = SizeOf(Zahlenformat1) ;
Protected max   = maxlg - 1             ;warum maxlg-1, siehe PB Hilfe Strukturen
Protected j                             ;Schleifenvariable

;letztes Komma wird Punkt
If CountString(*z\s, ",")
   
   ;ersetzt *z\s = ReplaceString(*z\s, ",", ".") allerdings nur das letzte Komma 
   For j = max To 0 Step -1
      If *z\c[j] = komma
         *z\c[j] = punkt
         Break
      EndIf
   Next
 
EndIf
    
If CountString(*z\s, ".")

    ;wo ist der Punkt ?
    For j = 0 To max    
      
      If *z\c[j] = punkt
          
          ;Zahl mit Punkt hat keine Kommastellen
          If *z\c[j+1] = char0  
             *z\c[j] = null
             *z\c[j+1] = null
             If *z\drei = drei: *z\c[j+2] = null: EndIf           
         
         ;Zahl mit Punkt hat 1 Kommastelle
          ElseIf *z\c[j+2] = char0  
             *z\c[j] = *z\c[j+1]
             *z\c[j+1] = null
             If *z\drei = drei: *z\c[j+2] = null: EndIf           
         
         ;Zahl mit Punkt hat 2 Kommastellen
          ElseIf *z\c[j+3] = char0  
             *z\c[j] = *z\c[j+1]    ;1 nach links schieben
             *z\c[j+1] = *z\c[j+2]  ;1 nach links schieben
             *z\c[j+2] = char0      ;letzte Stelle löschen   
             If *z\drei = drei: *z\c[j+2] = null: EndIf           
         
          ;Zahl mit Punkt hat 3 Kommastellen
          ElseIf *z\c[j+4] = char0  
             *z\c[j] = *z\c[j+1]    ;1 nach links schieben
             *z\c[j+1] = *z\c[j+2]  ;1 nach links schieben
             *z\c[j+2] = *z\c[j+3]  ;1 nach links schieben   
             *z\c[j+3] = char0      ;letzte Stelle löschen   
             If *z\drei <> drei     ;keine 1/10 cent
                If *z\c[j+2] > '4'
                   *z\c[j+1] + 1    ;aufrunden
                EndIf
                *z\c[j+2] = char0: 
             EndIf           
         
          EndIf
      
          Break 
      
      EndIf
    
    Next 
    
Else
    
    ;kein Punkt, 2 Nullen anhängen bzw. 3 Nullen
    For j = 0 To max
        If *z\c[j] = char0
           *z\c[j] = null
           *z\c[j+1] = null
           If *z\drei = drei
             *z\c[j+2] = null
           EndIf           
           Break
        EndIf
    Next    
    
EndIf

ProcedureReturn Val(*z\s) ;Longwert zurückgeben

EndProcedure

;Demo=================================================

z.Zahlenformat1
z\drei = '3'

z\s = "123"
Debug UsingCent2(z)

z\s = "123,"
Debug UsingCent2(z)

z\s = "123,4"
Debug UsingCent2(z)

z\s = "123,45"
Debug UsingCent2(z)

z\s = "123,456"
Debug UsingCent2(z)

z\drei = ''

z\s = "123,4"
Debug UsingCent2(z)

z\s = "123,45"
Debug UsingCent2(z)

z\s = "123,456"
Debug UsingCent2(z)