motorcross
Goto Top

Dezimalzahlen über Batch verarbeiten

Hallo Administratoren,

ich programmiere gerade einen Geldwechseler, der 2 Euromünzen, 1 Euromüzen und 0,10 Euromünzen wechselt.
Nur habe ich ein problem mit den Dezimalzahlen.
Hier erstmal mein Script für GANZE Euro
@Echo off
:aa
set /p alt=Geld:
:bb
if %alt% GEQ 50 echo Error zu viel Geld!!&pause&goto aa
:cc
if %alt% GEQ 2 set /a eurodeux=%eurodeux%+1&set /a alt=%alt%-2
if %alt% GEQ 1 set /a euroun=%euroun%+1&set /a alt=%alt%-1
if %alt%==0 goto gg
goto cc
echo %eurodeux%
echo %euroun%

:gg
if %eurodeux%==0 goto ff
call 2.00-1.vbs
set /a eurodeux=%eurodeux%-1
goto gg

:ff
if %euroun%==0 exit
call 1.00.vbs
set /a euroun=%euroun%-1
goto ff

Beschreibung
1. Benötigte Geld wird eingegeben
2. Es wird gezählt wie viele Münzen den Betrag ergeben der in der Variable %alt% gespeichert ist.
3. Das Geld wird ausgezahlt:
"call 2.00-1.vbs" bedeutet das jetzt eine 2 Euromünze ausgezahlt wird.
"call 1.00.vbs" bedeutet das jetzt eine 1 Euromünze ausgezahlt wird.

Wichtig:
Ich würde gerne in diesem Script auch dezimalzahlen verarbeiten.
z. B. das man 15.10 eingibt und dann das z.B. 14 2 Euromünzen und 1 1Euromünze und 1 0,10 Euromünze ausgezahlt wird.
Die 0,10.vbs würde dann immer eine 0,10 Euomünze auszahlen.
Kann man das irgendwie programmieren und wenn ja wie?
Ich würde mich über Hilfe und Beispiele freuen!
Gruß Motorcross

Content-ID: 140253

Url: https://administrator.de/contentid/140253

Ausgedruckt am: 22.11.2024 um 14:11 Uhr

bastla
bastla 09.04.2010 um 18:24:22 Uhr
Goto Top
Hallo motorcross!

Etwa so:
@echo off & setlocal
:aa
set /p alt=Geld:
:bb
for /f "tokens=1-2 delims=." %%a in ("%alt%") do if [%%b]== (set /a alt=%%a*100) else (set /a alt=%%a*100+1%%b-100)  
if %alt% GEQ 5000 echo Error zu viel Geld!! & pause & goto aa
:cc
if %alt% GEQ 200 (
    set /a eurodeux+=1
    set /a alt-=200
    goto :cc
)
:dd
if %alt% GEQ 100 (
    set /a euroun+=1
    set /a alt-=100
    goto :dd
)
set /a centdix=alt/10
echo %eurodeux%
echo %euroun%
echo %centdix%

:gg
if %eurodeux%==0 goto ff
call 2.00-1.vbs
set /a eurodeux-=1
goto gg

:ff
if %euroun%==0 goto hh
call 1.00.vbs
set /a euroun-=1
goto ff

:hh
if %centdix%==0 goto :eof
call "0,10.vbs"  
set /a centdix-=1
goto hh
Es wird vorausgesetzt, dass keine oder genau 2 Nachkommastellen eingegeben wurden, und falls die Eingabe nicht auf 10 Cent genau ist, fallen die überzähligen Cent einfach weg (also würde zB eine Eingabe von 15.18 als Ergebnis 7 / 1 / 1 liefern) ...
Da Batch ja nun wirklich nicht mit Dezimalzahlen umgehen kann, müssen aus den Euro eben Cent (und damit wieder ganzzahlige Werte) werden - deshalb die Multiplikation mit 100 ...

Noch ein Hinweis zur etwas gewöhnungsbedürftig aussehenden Formel
set /a alt=%%a*100+1%%b-100
Da in Batch eine mit der Ziffer 0 beginnende Zahl als Oktalzahl interpretiert wird, würde die einfachere Variante
set /a alt=%%a*100+%%b
bei der Eingabe von 08 oder 09 Cent zu einem Fehler führen - durch das Voranstellen von 1 wird daraus aber zunächst zB 108 und durch die folgende Subtraktion von 100 der verarbeitbare Wert 8.

Hinsichtlich der Schreibweise von zB "set /a alt-=200" gibt die Onlinehilfe zu "set" nicht ganz so viel her, deshalb auch dazu eine kurze Erklärung: Es wird damit der Interpreter einfach angewiesen, vom derzeitigen Wert der Variablen %alt% 200 zu subtrahieren und das Ergebnis wieder in %alt% zu speichern.

Grüße
bastla

P.S.: Natürlich ließe sich die Ermittlung der Münzanzahl auch sehr einfach ohne Schleifen realisieren (auf vielfachen Wunsch in der kommentierten Version face-wink) und damit als Ersatz der Zeilen 7 bis 18 etwa so formulieren:
:: Betrag in Cent durch 200 ganzzahlig (kann Batch ohnehin nicht anders) dividieren,
:: um die Anzahl der 2-Euro-Münzen zu ermitteln und in der Variablen %eurodeux% zu speichern
set /a eurodeux=alt/200
:: Restbetrag in Cent ermitteln, indem für jede 2-Euro-Münze 200 Cent abgezogen werden -
:: vereinfacht durch Multiplikation anstelle einer Schleife, und in der für "set /a"-Anweisungen  
:: zulässigen verkürzten Variablenschreibweise (ohne Prozentzeichen)
set /a alt-=eurodeux*200
:: analog zur Vorgangsweise für die 2-Euro-Münzen die Ermittlung der Anzahl von 1-Euro-Münzen ...
set /a euroun=alt/100
:: ... und wiederum Berechnung des verbleibenden Betrages
set /a alt-=euroun*100
Biber
Biber 09.04.2010 um 18:38:53 Uhr
Goto Top
[OT]
Moin Motorcross, moin bastla,

um diesen beiden hartnäckigen Gerüchten entgegenzuwirken:

  • nein, es ist schon dem Bergfest von Helmut Kohls Amtszeit nicht mehr so, dass Batchschnipsel immer ein bisschen ruckeln, wenn sie Kommentarzeilen überspringen müssen. Die Prozessoren sind echt spürbar flotter geworden.

  • nein, es ist auch nicht so, dass durch das Setzen von Codetags automatisch alle Kommentarzeilen die Schriftfarbe weiß bekommen.

So alle 5 cm könnte doch ruhig mal eine mit "REM " oder "::" beginnende und von einem Halbsatz gefolgte Erklärung folgen, oder...? *wimpernklapp*

Falls es sich um die weit verbreiteten Oneliner handelt will ich nichts sagen....

Grüße
Biber

[Edit] @bastla Na gut, wenn du jetzt schon was nachgetragen hast, dann will ich mal nicht auch noch nachtragend sein *gg [/Edit]
[/OT]
bastla
bastla 09.04.2010 um 18:41:24 Uhr
Goto Top
@Biber
Ruhig Brauner *SCNR* - ist ja schon (zumindest ein wenig) was in der Richtung nachgereicht ... face-wink

Grüße
bastla
Biber
Biber 09.04.2010 um 22:35:22 Uhr
Goto Top
Okay, okay, bastla,

ich nehme alles zurück. face-wink
Höchstes und ernst gemeintes Lob für die Bereitstellung, Erläuterung und Erklärung deiner Lösung. face-wink

Dann muss ich eben allein Motorcross anzählen, der hatte ja gebeten:
Ich würde mich über Hilfe und Beispiele freuen!
Bitte auch als versuchte Hilfe annehmen:
Wenn schon vollständiger Verzicht auf jegliche Kommentare in einen Script-Schnipsel,
dann bestenfalls bei (wirklich) selbst erklärenden Variablen- und Unterprogramm/Funktionsnamen.

Wenn aber aufgerufene Unterroutinen kommentarlos als :aa, :bb, :cc...., :gg aufgerufen werden, dann mindert das auf jeden Fall die Pfleg-, Wart- und Nachvollziehbarkeit des Sourcecodes.

Und irgendwann wirst auch du vor der Situation stehen, dass du einen Schnipsel anpassen musst, den du vor 8 oder 18 Monaten eben mal flüssig runtergetippselt hast und den du nun aber nicht mehr auf Anhieb nachvollziehen kannst.

...aber wozu red' ich.... ich hatte mal eine Praktikantin, die.... jedenfalls ist sorgfältige Codedokumentation nicht das einzige Kriterium, das zählt.

Grüße
Biber
76109
76109 10.04.2010 um 13:19:23 Uhr
Goto Top
Hallo zusammen!

Wenn doch sowieso ein VB-Script aufgerufen wird, warum dann das Ganze so umständlich?

Das läßt sich doch mit einem simplen VB-Script wesentlich einfacher gestalten und ist dabei auch noch ohne Aufwand beliebig erweiterbarface-wink

Batch:
@Echo off
set /p Wert="Geldwert eingeben: "  
cscript //nologo Geldwechsel.vbs %Wert%

VB-Script:
Dim Anzahl, Betrag, Wechselgeld, a, w
    
If WScript.Arguments.Count <> 1 Then WScript.Quit

Wechselgeld = Array(200, 100, 50, 20, 10, 5, 2, 1)
    
Betrag = CDbl(WScript.Arguments(0)) * 100
    
For w = 0 To UBound(Wechselgeld)
    Anzahl = Betrag \ Wechselgeld(w)
        
    For a = 1 To Anzahl
        Select Case Wechselgeld(w)
            Case 200
               WScript.Echo "2 Euro"  
            Case 100
               WScript.Echo "1 Euro"  
            Case 50
               WScript.Echo "50 Cent"  
            Case 20
               WScript.Echo "20 Cent"  
            Case 10
               WScript.Echo "10 Cent"  
            Case 5
               WScript.Echo "5 Cent"  
            Case 2
               WScript.Echo "2 Cent"  
            Case 1
               WScript.Echo "1 Cent"  
        End Select
    Next
        
    Betrag = Betrag Mod Wechselgeld(w)
Next
Der Code sollte - so hoffe ich zumindest, soweit selbsterklärend seinface-wink

Gruß Dieter
bastla
bastla 10.04.2010 um 13:35:29 Uhr
Goto Top
Hallo Dieter!

Dann aber doch gleich:
Dim Anzahl, Betrag, Wechselgeld, a, w
    
If WScript.Arguments.Count <> 1 Then WScript.Quit

Wechselgeld = Array(200, 100, 50, 20, 10, 5, 2, 1)
WechselgeldText = Array("2 Euro","1 Euro","50 Cent","20 Cent","10 Cent","5 Cent","2 Cent","1 Cent")  
    
Betrag = CDbl(WScript.Arguments(0)) * 100
    
For w = 0 To UBound(Wechselgeld)
    Anzahl = Betrag \ Wechselgeld(w) 'ganzzahlige Division  
    If Anzahl > 0 Then WScript.Echo Anzahl & " * " & WechselgeldText(w)          
    Betrag = Betrag Mod Wechselgeld(w)
Next
oder meinetwegen mit
    For a = 1 To Anzahl
        WScript.Echo WechselgeldText(w)
    Next
anstelle der Zeile 12 ...

Grüße
bastla
76109
76109 10.04.2010 um 13:45:29 Uhr
Goto Top
Hallo bastla!

Sofern es nur bei einer Textausgabe bleiben soll, dann natürlich optimalface-wink

Falls aber irgendwelche Routinen aufgerufen werden sollen, dann muss die Textausgabe nur durch einen entsprechenden Aufruf ersetzt werden. So habe ich zumindest gedenktdenktface-wink

Gruß Dieter

PS
Anzahl = Betrag \ Wechselgeld(w) 'ganzzahlige Division
Sehr schön. An diesen Hinweis habe ich mit meinem Alzheimerhirn auch nicht gedachtface-wink
bastla
bastla 10.04.2010 um 13:51:15 Uhr
Goto Top
Hallo Dieter!
Falls aber irgendwelche Routinen aufgerufen werden sollen, dann muss die Textausgabe nur durch einen entsprechenden Aufruf ersetzt werden.
Ist natürlich richtig ... face-smile

... aber auch in diesem Fall sollte ein einziger Aufruf mit den Parametern Anzahl und Münzenart genügen ...

[Edit] Zur ganzzahligen Division: Hinsichtlich der "For-Next"-Schleife wäre diese eigentlich gar nicht erforderlich ... [/Edit]

Grüße
bastla
76109
76109 10.04.2010 um 14:02:19 Uhr
Goto Top
Hallo bastla!

Zitat von @bastla:
... aber auch in diesem Fall sollte ein einziger Aufruf mit den Parametern Anzahl und Münzenart genügen ...
Die Anzahl bzw. die Einzelausgabe habe ich nur aufgrund der Einzelaufrufe in der Vorgabe-Batch genommen, weil ich ja nicht weiß, was tatsächlich noch hintendran hängt. D.h. ob am Ende eventuell eine Art Einzelimpuls erforderlich ist?

Gruß Dieter
Biber
Biber 10.04.2010 um 14:25:40 Uhr
Goto Top
Schade, didi1954 und bastla,

da habe ich wieder zu sehr getrödelt.. ich wollte auch mitspielen und hatte einen ähnlichen Ansatz wie bastla.

Also der Vollständigkeit halber meine Variante:
' BiberWexler.vbs -- Anpassung von didi1954s Ansatz  
Dim Anzahl, Betrag, Wechselgeld, a, w 

If WScript.Arguments.Count <> 1 Then WScript.Quit 

' Münzen haben einen Wert in Cent, ein Label und eine Anzahl Münzen  
'Ich habe darauf verzichtet, EIN Array der Länge 8 x 3 Elemente zu machen  
Wechselgeld   = Array(200, 100, 50, 20, 10, 5, 2, 1) 
WechselLabel  = Array(" 2 Euro", " 1 Euro","50 Cent","20 Cent","10 Cent"," 5 Cent"," 2 Cent", " 1 Cent")  
WechselAnzahl = Array(  0,   0,  0,  0,  0, 0, 0, 0)     

Betrag = CDbl(WScript.Arguments(0)) * 100 

For w = 0 To UBound(Wechselgeld) 
    Anzahl = Betrag \ Wechselgeld(w) 
'    WScript.Echo "Anzahl " & Anzahl   
    For a = 1 To Anzahl 
        If Wechselgeld(w) Then WechselAnzahl(w) = WechselAnzahl(w) + 1
        
    Next 
    
    Betrag = Betrag Mod Wechselgeld(w) 
Next
For w = 0 To UBound(WechselAnzahl) 
   If WechselAnzahl(w) then
    WScript.Echo Right("   "& WechselAnzahl(w),3) & " x " & WechselLabel(w)  
   End if  
Next    
Output:
>cscript BiberWeXler.vbs 57,33
 28 x  2 Euro
  1 x  1 Euro
  1 x 20 Cent
  1 x 10 Cent
  1 x  2 Cent
  1 x  1 Cent

Grüße
Biber
76109
76109 10.04.2010 um 14:54:16 Uhr
Goto Top
Hallo Biber!

Spätzünderface-wink

Wobei die Codezeile 18:
If Wechselgeld(w) Then WechselAnzahl(w) = WechselAnzahl(w) + 1 
für mich keinen Sinn ergibt, zumal der Wert immer True ist, weil das Wechsgeld-Array nur True-Werte enthält und somit unnötig ist. Auch desdewegen, weil die Schleife Anzahl ja nur durchlaufen wird, wenn Anzahl > 0 ist.

Gruß Dieter
bastla
bastla 10.04.2010 um 15:06:18 Uhr
Goto Top
Hallo Biber!
da habe ich wieder zu sehr getrödelt..
Dafür hast Du aber die schönste Ausgabe produziert ... face-smile
ich wollte auch mitspielen
"Spielen" ist ja sowieso das Stichwort für den ganzen Thread ... face-wink
Wie Dieter sind auch mir die Zeilen 17 bis 20 aufgefallen - die würde ich etwas unspektakulärer gestalten und durch
WechselAnzahl(w) = Anzahl
ersetzen.

Grüße
bastla
bastla
bastla 10.04.2010 um 15:10:02 Uhr
Goto Top
Hallo Dieter!
... weil ich ja nicht weiß, was tatsächlich noch hintendran hängt. D.h. ob am Ende eventuell eine Art Einzelimpuls erforderlich ist?
Auch einen solchen würde ich im aufgerufenen Unterprogramm (genügend oft face-wink, aber für die einzelnen Münzarten auf die gleiche Weise) auslösen - nur, wenn es tatsächlich irgendwelche "Sonderbehandlungen" geben müsste, würde ich zu "Select Case" greifen ...

Grüße
bastla
76109
76109 10.04.2010 um 15:36:44 Uhr
Goto Top
Hallo bastla!

Zitat von @bastla:
Hallo Biber!
> da habe ich wieder zu sehr getrödelt..
Dafür hast Du aber die schönste Ausgabe produziert ... face-smile
Stimmt, ist mir garnicht aufgefallen. Die Codezeile 18 hat mich wohl zu sehr verwirrtface-smile

Gruß Dieter
Biber
Biber 10.04.2010 um 16:11:17 Uhr
Goto Top
Moin bastla und didi1954,

klar, ihr habt natürlich Recht mit den etwas sehr verspielten Zeilen 17ff.
Zum Wechseln von ein paar Euronen reicht jedenfalls dieses hier vollkommen.
' BiberWexler.vbs -- V.002 Anpassung von didi1954s Ansatz  
Dim Betrag, w, Wechselgeld, WechselAnzahl, WechselLabel 

If WScript.Arguments.Count <> 1 Then WScript.Quit 

' Münzen haben einen Wert in Cent, ein Label und eine Anzahl Münzen  
'Ich habe darauf verzichtet, EIN Array der Länge 8 x 3 Elemente zu machen  
Wechselgeld   = Array(200, 100, 50, 20, 10, 5, 2, 1) 
WechselAnzahl = Array(  0,   0,  0,  0,  0, 0, 0, 0)     
WechselLabel  = Array(" 2 Euro", " 1 Euro","50 Cent","20 Cent","10 Cent"," 5 Cent"," 2 Cent", " 1 Cent")  

Betrag = (WScript.Arguments(0)) * 100 

For w = 0 To UBound(Wechselgeld) 
    WechselAnzahl(w) = Betrag \ Wechselgeld(w) 
    Betrag = Betrag Mod Wechselgeld(w) 
Next

For w = 0 To UBound(WechselAnzahl) 
   If WechselAnzahl(w) then
    WScript.Echo Right("   "& WechselAnzahl(w),3) & " x " & WechselLabel(w)  
   End if  
Next

...ich spiele ja immer gerne mit euch mit...

Grüße
Biber
76109
76109 10.04.2010 um 17:18:53 Uhr
Goto Top
Hallo Biber!

Sehr schön. Genau nach meinem Geschmackface-wink

...ich spiele ja immer gerne mit euch mit...
ich auch face-smile

Gruß Dieter