Seite 1 von 1

formatierte Zahl mit 100 malnehmen, wie gehts schneller

Verfasst: 01.05.2008 10:53
von hjbremer
ich habe eine Liste mit mehr als 5000 Zeilen. In den Zeilen stehen formatierte Beträge z.B. 10.20
Diese Beträge werden auf Knopfdruck mit anderen Zahlen in der Zeile verrechnet und das Ergebnis wieder in die Zeile eingetragen.
Dabei ist jede zehntel Sekunde wertvoll, denn Warten ist ätzend.

Rechne darum in Cent und zur Umwandlung hier einige Beispiele mit MwSt, Frage: geht es noch schneller oder bei gleicher Leistung einfacher ?

Code: Alles auswählen

#zahllg = 15

Structure Betrag
 StructureUnion 
  euro.s{#zahllg}
  c.c[0]            ;wird hier nur für die Prüfung auf vorhandenen Punkt benutzt
 EndStructureUnion
 euromw1.s{#zahllg}
 euromw2.s{#zahllg}
 euromw3.s{#zahllg}
EndStructure 

max = 25000

;Betrag in Euro wird in Cent umgewandelt
;+ 19 % Mehrwertsteuer
;Cent zurück in Euro

;Methode mit CopyMemory inclusive Test auf vorhandenen Punkt

a=GetTickCount_()

  For j = 1 To max
  
      wert.Betrag\euro = RSet("123.45",#zahllg)   ;RSet(...) könnte aus einer Tabelle kommen
          
      If wert\c[#zahllg-3] = 46
       
         CopyMemory(@wert\euro,@wert\euro+1,#zahllg - 3)
         cent = Val(wert\euro) * 1.19
       
      Else
      
         ;Fehler kein Punkt vorhanden
      
      EndIf
      
      wert\euromw1 = RSet(Str(cent),#zahllg)    
      CopyMemory(@wert\euromw1+1,@wert\euromw1,#zahllg - 2)
      PokeC(@wert\euromw1+#zahllg-3,'.')   ;wert\euromw1 könnte in eine Tabelle geschrieben werden
      
  Next
          
b=GetTickCount_()-a


;meine normale Methode

a=GetTickCount_()

  For j = 1 To max
      
      string$ = "123.45"
      cent = ValF(string$) * 119
  
      euro$ = Str(cent)
      lg = Len(euro$)
      euro$ = Left(euro$,lg-2)+"."+Right(euro$,2)
      wert\euromw2 = RSet(euro$,#zahllg)

  Next
    
c=GetTickCount_()-a

;mit Float

a=GetTickCount_()

  For j = 1 To max
      string$ = "123.45"
      euro.f = ValF(string$) * 1.19
  
      euro$ = StrF(euro.f)
      wert\euromw3 = RSet(euro$,#zahllg)

  Next
    
d=GetTickCount_()-a
MessageRequester("", wert\euromw1+"="+Str(b)+#LF$ + wert\euromw2+"="+Str(c)+#LF$ + wert\euromw3+"="+Str(d)+#LF$)


Verfasst: 01.05.2008 11:14
von STARGÅTE
bin irgendwie verwirrt.

wenn du einen Euro Betrag einfach in Cent umwandeln willst reicht doch ein einfacher ReplaceString($Euro, ".", "")?

schon wird aus 123.45 -> 12345

dann knallst du da von mir aus irgend n MWSt drauf, und machst das komma wieder rein

Verfasst: 01.05.2008 11:22
von ZeHa
Das geht aber nur, wenn er "glatte" Beträge hat, also solche die 2 Nachkommastellen haben. Wenn eine Zahl mal 3 oder 1 oder keine Nachkommastelle hat, geht es mit Deinem Vorgehen nicht mehr.

Daher müßte man da eben aufpassen, daß immer glatte Beträge vorhanden sind.

Verfasst: 01.05.2008 11:23
von ZeHa
Ich weiß jetzt eh nicht genau was Du vorhast, aber evtl. wäre es auch sinnvoller, die Liste mit "echten" Zahlen zu erstellen und sie nur dann, wenn sie ausgegeben werden müssen, per StrF() oder Str() in eine formatierte Zahl zu verwandeln.

Könnte je nach Zweck schonmal die bessere Lösung sein.

Zahlen konvertieren

Verfasst: 01.05.2008 14:49
von AND51
Wie schon gesagt wurde, kostet das Konvertieren von Zahlen viel Zeit.
Es ist viel schneller, intern mit richtigen Zahlen zu rechnen und wie nur wenn nötig in Text umzuwandeln. Wenn man den Text zweimal konvertieren muss, lohnt es sich hinsichtlich des Zeitgewinns auf jeden Fall, mit echten Zahlen zu rechnen. Nicht nur weil die Konvertierung entfällt, sondern auch weil man sich um die Nachkommastellen und die Multiplikation mit der Mehrwertsteuer keine Gedanken machen muss.

@ Stargate:
Text löscht man richtig, indem manRemoveString() statt ReplaceString() verwendet. <)

Verfasst: 01.05.2008 16:47
von hardfalcon
Rechne in Cent, multipliziere mit 119, dann kriegst du Hunderstel Cent raus. Wenn du die wieder in Cent haben willst, schreib dir ne kleine Procedure, die Kaufmännische Rundung ohne Float hinkriegt (z.B. indem du schaust, was bei einem Modulo durch 100 übrig bleibt - wenn dieser Wert über 49 ist, rundest du auf, ansonsten rundest du ab).

Wenn du mit Floats multiplizierst, riskierst du nämlich, dass als Produkt auch ein Floatwert rauskommt, was natürlich unerwünscht ist.

//EDIT: Örks, sry, da hab ich wohl dein Posting falsch verstanden gehabt... Hab nich gleich kapiert, dass das Float-Verfahren in deinem Code nur als Vergleich und als Beispiel, wie man es nicht machen sollte, dient... <)

Verfasst: 01.05.2008 23:26
von hjbremer
Stargate Klasse Vorschlag, denn das Einfache in Verbindung mit CopyMemory ist etwa gleichschnell, aber nur wenn man mit einem Fixstring arbeitet.
Dafür aber schöner, flexibler und einfacher !

Code: Alles auswählen

      #zahllg = 15
      euromw.s{#zahllg}

      cent$ = "123.45"                     ;könnte aus einer Tabelle kommen
      cent$ = ReplaceString(cent$,".","")
      
      cent = Val(cent$) * 1.19
      
      euromw = RSet(Str(cent),#zahllg)    

      CopyMemory(@euromw+1,@euromw,#zahllg - 2)
      PokeC(@euromw+#zahllg-3,'.')   ;euromw könnte in eine Tabelle geschrieben werden
      

Verfasst: 02.05.2008 16:09
von mk-soft
Frage,

Muss man nicht kaufmännisch mit 6 stellen hinter komma rechnen.

Intern immer mit Ganzzahlen rechnen und nur die Ausgabe anpassen

Edit:

Code: Alles auswählen

Procedure.s StrE(value.q)
  
  Protected result.s, temp.s, len
  
  temp = StrQ(value)
  len = Len(temp)
  Select len
    Case 1
      result = "0.0" + temp
    Case 2
      result = "0." + temp
    Default
      result = Left(temp, len - 2) + "." + Right(temp, 2)
  EndSelect
  
  ProcedureReturn result
  
EndProcedure

Procedure.q ValE(value.s)
  
  Protected result.q, temp.d
  temp = ValD(value)
  temp * 100
  result = temp
  ProcedureReturn result
  
EndProcedure

Debug StrE(ValE("0.01"))
Debug StrE(12)
Debug StrE(123)
FF :wink: