3. StructureUnion und Euro in Cent umwandeln

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.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

3. StructureUnion und Euro in Cent umwandeln

Beitrag 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))
 
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
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 »

Wieso nicht einfach das Komma mit 'RemoveString()' rauslöschen und dann mit 'Val()' zur Zahl machen?
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag 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))
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag 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)

Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Antworten