Euro in Cent umwandeln in einer Miniversion

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

Euro in Cent umwandeln in einer Miniversion

Beitrag von hjbremer »

Für alle die Euro-Beträge aus einer Liste mit formatierten Zahlen in Cent umwandeln müssen um dann mit Ganzzahlen weiterrechnen wollen.
Es wird vorausgesetzt, das jede Zahl 2 Kommastellen hat.

Hier meine Miniversion im Vergleich zu 3 anderen Standardversionen.

Fällt jemandem etwas schnelleres ein, so möge er mir dies unbedingt mitteilen, denn ich muß meine Liste mit über 5000 Zeilen häufig neu berechnen. Ich habe die Daten aber nicht in Feldern zusätzlich abgelegt. Ist mir zu aufwändig.

Code: Alles auswählen

Procedure uc(euro$)

    ProcedureReturn ValF(euro$)*100 

EndProcedure

Procedure uc0(euro$)

    ProcedureReturn Val(ReplaceString(euro$,".","",1)) 

EndProcedure

Procedure uc1(euro$)

    ProcedureReturn Val(RemoveString(euro$,".",1)) 

EndProcedure

Procedure uc2(euro$)

    *z = @euro$
    lg = Len(euro$) -3
    
    CopyMemory(*z,*z+1,lg)
    PokeC(*z,' ')
    
    ProcedureReturn Val(euro$)

EndProcedure

;Test ohne Debugger !!!

max = 100000

a=GetTickCount_() 
 For j = 1 To max
   cent = uc("61023.45")
 Next
b=GetTickCount_()-a 

a=GetTickCount_() 
 For j = 1 To max
   cent0 = uc0("61023.45")
 Next
c=GetTickCount_()-a 

a=GetTickCount_() 
 For j = 1 To max
   cent1 = uc1("61023.45")
 Next
d=GetTickCount_()-a 

a=GetTickCount_() 
 For j = 1 To max
   cent2 = uc2("61023.45")
 Next
e=GetTickCount_()-a 

MessageRequester("",Str(cent)+" Normal  ="+Str(b)+#LF$+Str(cent0)+" Replace ="+Str(c)+#LF$+Str(cent1)+" Remove ="+Str(d)+#LF$+Str(cent2)+" Memory ="+Str(e)) 
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
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Kleine Beschreibung wäre zu jeder Prozedur angebracht; du musst außerdem auch vernünftige namen für die prozeduren vergeben. Durch kürze Prozedurnamen wird deine Prozedur sowieso nicht schneller und "zu viel zu tippen" gibt's auch nicht als Ausrede, da das Autovervollständigen schon erfunden wurde.

Ich arbeite gerade an Verbesserungen und werde gleich Posten.
Bin sicher, da kann man noch was rausholen.

Schimpfen muss ich auch:
uc0() - Wozu gibt's da RemoveString(), um etwas zu entfernen? :wink:


// Edit:
> Ist mir zu aufwändig
Du liest einen Betrag als String aus der Liste, konvertierst sie zum Rechnen in eine Zahl und dann hinterher wieder zurück in einen String? Performance, leb wohl... :lol:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

mit Liste ist ein ListIconGadget gemeint und da liefert PB nur Strings zurück oder ?

und Removestring siehe uc1 !
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
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Aber GetGadgetItemData() nicht, wenn du das Data Feld mitbenutzen würdest, sofern möglich.
Nix Beschreibung, jetzt hab ich verstanden: ALLE Prozeduren wandeln in Cent um und du willst die schnellste. Jetzt verstehe ich auch den Unterschied zwischen uc0 ohne und uc1 mit RemoveString.

Sorry, das habe ich jetzt erst verstanden. Eine Prozedur habe ich schon fertig, ca. 8x schneller als uc0. Tüftle noch.

Übrigens: Deine letzte Prozedur funzt nicht... Du verschiebst alle zeichen im Buffer 1 nach rechts?
3 Fehler:

1. Die Speicherbereiche überlappen sich - MoveMemory() ist hier sicherer, wenn auch langsamer
2. Du verschiebst alle Zeichen um 1 nach rechts OHNE den Speicher zu re-allokieren (ReAllocateMemory()); BÖÖÖSE
3. Du setzt vor die ganze Zahl ein Leerzeichen? Wozu, damit Val() immer 0 zurückgibt?
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Macht Platz für den Gewinner:

Code: Alles auswählen

Procedure EurToCnt(Euro$)
	Protected *digit2.Character=@Euro$+MemoryStringLength(@Euro$)<<#PB_Compiler_Unicode-SizeOf(Character)
	Protected *digit1.Character=*digit2-SizeOf(Character)
	Protected *comma.Character=*digit1-SizeOf(Character)
	Swap *comma\c, *digit2\c
	Swap *comma\c, *digit1\c
	ProcedureReturn Val(Euro$)
EndProcedure

Debug EurToCnt("61023.45")
Hatt erst 2 prozeduren, diese hier war aber in 2 von 3 Fällen schneller.

Speedtest bei 100.000 rpm:
  • Normal = 313
    Replace= 93
    Remove = 79
    EurToCnt = 62
Speedtest bei 1.048.576 rpm:
  • Normal = 4375
    Replace= 1343
    Remove = 1078
    EurToCnt = 813
Speedtest bei 16.777.216 rpm:
  • Normal = 74297
    Replace= 18063
    Remove = 13047
    EurToCnt = 10625
Memory entfällt, da diese Prozedur nicht funktioniert. Der Gewinner ist... tadaaaa... jedes Mal ICH! :lol:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Deine geniale Version etwas schneller

Code: Alles auswählen

Procedure EurToCnt(*mem) 
   Protected *digit2.Character=*mem+MemoryStringLength(*mem)<<#PB_Compiler_Unicode-SizeOf(Character) 
   Protected *digit1.Character=*digit2-SizeOf(Character) 
   Protected *comma.Character=*digit1-SizeOf(Character) 
   Swap *comma\c, *digit2\c 
   Swap *comma\c, *digit1\c 
EndProcedure 

   euro$= "61023.45"
   *zeiger = @euro$
   EurToCnt(*zeiger)
   cent = Val(euro$)
   Debug cent
   
Und da dir meine CopyMemory Version nicht gefällt
hier im Prinzip das Gleiche nur anders und genau so schnell wie oben.

Code: Alles auswählen

Structure ZahlenFormatC
 c.c[0]
EndStructure 
 
Procedure EurToCnt1(*z.ZahlenFormatC) 
   
   lg = MemoryStringLength(*z) - 1
   
   *z\c[lg-2] = *z\c[lg-1] 
   *z\c[lg-1] = *z\c[lg] 
   *z\c[lg]   = 0 
   
EndProcedure 

   euro$= "61023.45"
   *zeiger = @euro$
   EurToCnt1(*zeiger)
   cent = Val(euro$)
   Debug cent
   
Ich denke noch schneller wird man nur noch mit Assembler Befehlen. Ein Schwachpunkt ist MemoryStringLength. Ich kenn mich damit leider nicht aus, aber es gibt doch den Befehl _strstr. Gibt es nicht vielleicht sowas wie _strlen ?
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
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Irre ich mich, oder hast du bei meiner Prozedur im Prinzip nur das Val() + das Return ausgegliedert?
P.S.: Deine 2. Version ist soweit ich das sehe, vom Prinzip her ähnlich wie meine, oder?

MemoryStringLength ist schon okay, die Alternative wäre StringByteLength, aber letzteres arbeitet ohne Pointer und ist daher hier ungeeignet.

P.S.: Deine 2. Version funktioniert nur im ASCII-Modus, sie wird in Unicode nicht funktionieren. statt in der ersten Zeile -1 zu rechnen, nimm lieber -SIzeOf(Character)
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Solch eine Funktion hat doch ueberhaupt keinen Nutzen. Was nuetzt die
Geschwindigkeit wenn die Sicherheit darunter zu leiden hat?
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

edel, du hättest nur dann Recht, wenn hjbremer hier —wie immer in der Code-Tipps-Tricks-Ecke— einen Universalcode veröffentlichen würde.

Der Code hat sehr wohl einen Nutzen, schon mal die "Aufgabenstellung" gelesen? Wohl kaum!
Er sucht hier nach einer möglichst schnellen Prozedur für genau sein Problem: Eine Liste mit String-basierten Eurowerten, die immer 2 Nachkommastellen haben, in Cent umzuwandeln.
Die hier geposteten Codes dürften also nur exakt auf sein Problem zutreffen.

Natürlich hat er in das falsche Subforum gepostet. Aber da kein Mod den Thread hier mal nach Allgemein verschoben hat und du auch noch nach dem nicht vorhandenen allgemeinen Nutzen fragst, kann man davon ausgehen,
dass niemand außer mir sich diesen Thread durchgelesen hat.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

AND51 hat geschrieben:bla, bla bla bla bla bla, bla bla bla —bla bla bla bla bla-bla-bla-bla— bla bla bla bla.

bla bla bla bla bla bla bla, bla bla bla "bla" bla? bla bla!
bla bla bla bla bla bla bla bla bla bla bla bla: bla bla bla bla-bla bla, bla bla bla bla bla, bla bla bla.
bla bla bla bla bla bla bla bla bla bla bla bla.

bla bla bla bla bla bla bla bla. bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla, bla bla bla bla,
bla bla bla bla bla bla bla bla bla.
Bitte?
Naja, da kann man ja nur hoffen das wenigstens du verstehst, was da steht.
Antworten