Übersetzungsroutine
Boris Hoeller
- perl
0 Bogus0 Stefan Muenz0 Boris Hoeller0 Holger
Bittere, aber nicht uninterssante Aufgabe :
#!/usr/bin/perl
$betrag = <STDIN> # Eingabe z.B. "54.998,00"
(hier arbeitet jetzt das gesuchte Script:))))
print "$betrag lautet übersetzt in Worte $betrag_in_worten"; # Ausgabe dann "54.998,00 lautet übersetzt in Worte vierundfünfzigtausendneunhundertachtundneunzig"
Schulbeispiele, Erfahrungen, Ideen, Verweise oder ähnliches?
Vielen Dank für jegliche Info und Grüße aus Bonn
Bo
Bis zu welcher hoehe sollen die betraege gehen?
moeglich waere eine routine, welche den betrag von hinten her aufsplitted
zuerst die letzten beiden stellen hinter dem komma, dann die 3 bis zum ersten punkt vor dem komma...
usw. von hinten nach vorne.
dann die einzelnen wieder splitten und in worte konvertieren. das waere ne moeglichkeit. wenn es aber alle zahlen bis ins unendlich konvertieren soll wird es ein wenig groesser.
eine routine die das automatisch erledigt ist mir leider nicht bekannt.
cu
zuerst die letzten beiden stellen hinter dem komma, dann die 3 bis zum ersten punkt vor dem komma...
usw. von hinten nach vorne.dann die einzelnen wieder splitten und in worte konvertieren. das waere ne moeglichkeit. wenn es aber alle zahlen bis ins unendlich konvertieren soll wird es ein wenig groesser.
Ich wuerde es wohl auch so machen. Ist sicher garnicht so schwer. Die Dreierbloecke kann kan ja mit einer Subroutine uebersetzen.
Allerdings ist das mit dem Unendlich auch nicht so dramatisch, denn irgendwann kannst DU eine Zahl nichtmehr mit Worten bezeichnen, oder weisst du was hinter der quadrilliarde kommt ?
Viele gruesse, Thomas Hieck
hye :-)
Allerdings ist das mit dem Unendlich auch nicht so dramatisch, denn irgendwann kannst DU eine Zahl nichtmehr mit Worten bezeichnen, oder weisst du was hinter der quadrilliarde kommt ?
hinter der quadrilliarde kommt die
FANTASTILLION UND DANN DIE FANTASTILLIARDE :-)
so stehts im Lustigen Taschenbuch :-)
soviel (und noch mehr) hat nämlich Dagobert Duck
ok, cu
hi!
Allerdings ist das mit dem Unendlich auch nicht so dramatisch, denn irgendwann kannst DU
eine Zahl nichtmehr mit Worten bezeichnen, oder weisst du was hinter der quadrilliarde
kommt ?
Quintillion :)
bye, Frank!
Hi,
Ich wuerde es wohl auch so machen. Ist sicher garnicht so schwer. Die Dreierbloecke kann kan ja mit einer Subroutine uebersetzen.
Allerdings ist das mit dem Unendlich auch nicht so dramatisch, denn irgendwann kannst DU eine Zahl nichtmehr mit Worten bezeichnen, oder weisst du was hinter der quadrilliarde kommt ?
das Thema hatten wir gerade erst in de.sci.mathematik... :-)
Teile die Zahl in sechser-Blöcke auf. Der nullte Block sind die Tausender etc., danach folgen:
Mill (ionen, iarden),
Bill*,
Trill*,
Quadrill*,
Quintill*,
Sextill*,
Septill*,
Octill*,
Nonill*,
Dezill*,
usw. (hoffe, ich habe jetzt keinen Fehler gemacht...). Wenn es noch höher gehen soll: Eine Dezillion sind 10^(6*10), wobei die 10 in der Klammer sich in "Dez" ausdrückt. 10^100 hat der Sohn (Enkel?) Eines Kindes mal benamst, und zwar als "gogool", was überraschend simpel ist für eine Zahl, die 20 Stellen mehr hat als die Zahl der Atome im bekannten Universum. Eine Zahl mit 10^100 Ziffern (also 10^(10^100)) heißt übrigens gogoolplex... :-)
Du kannst also in etwa folgendermaßen vorgehen:
$zahl = "123.456.789,12";
$block = 0; # aktueller 6er-Block
@bname = ('','Mill','Bill','Trill',...);
if ($zahl =~ /^(.*),(.*)$/) { $zahl = $1; $komma = $2; } # Ganzzahl herstellen, Nachkommastellen speichern
$zahl =~ s/.//g; # Punkte entfernen
$string = &num2string($zahl,$block);
Jetzt brauchst Du nur noch die rekursive sub num2string, die folgendes macht:
Die Funktion num2string überlasse ich Dir ;-)
Cheatah
das Thema hatten wir gerade erst in de.sci.mathematik... :-)
Teile die Zahl in sechser-Blöcke auf. Der nullte Block sind die Tausender etc., danach folgen:
Mill (ionen, iarden),
Bill*,
Trill*,
Quadrill*,
Quintill*,
Sextill*,
Septill*,
Octill*,
Nonill*,
Dezill*,
usw. (hoffe, ich habe jetzt keinen Fehler gemacht...).
Als Noch-Mathematikstudent hab ich auch keine Probleme die Reihe fortzufuehren :-) Aber das war rein rethorisch gefragt, da die meisten doch sowieso die Quadrilliarde als letzte Zahl kennen.
Uebrigens wird im allgemeinen Sprachgebrauch nicht mehr als Milliarde benutzt. Das naechstehoehere bezeichnet man dann schon als Tausend-Milliarde. Vielleicht der Vorstellung wegen.
Wenn es noch höher gehen soll: Eine Dezillion sind 10^(6*10), wobei die 10 in der Klammer sich in "Dez" ausdrückt. 10^100 hat der Sohn (Enkel?) Eines Kindes mal benamst, und zwar als "gogool", was überraschend simpel ist für eine Zahl, die 20 Stellen mehr hat als die Zahl der Atome im bekannten Universum.
:-) GOGOOL klingt wirklich cool. Ich glaub das mit den Atomen war sogar untertrieben. Meines Wissen waren sogar Teilchen. Aber es reicht wohl, wenn es Uununununvorstellbar ist :-)
Eine Zahl mit 10^100 Ziffern (also 10^(10^100)) heißt übrigens gogoolplex... :-)
<menschelei>Klingt fast noch schoener :-) Sollten wir nicht gleich wieder aus dem Sprachgebrauch des Forums verbannen :-)</menschelei>
Die Funktion num2string überlasse ich Dir ;-)
Mir nicht, aber Boris machts sicher zuende. Hab gerade garkein Nerv dafuer.
Viele Gruesse, Thomas Hieck
Hi,
Als Noch-Mathematikstudent hab ich auch keine Probleme die Reihe fortzufuehren :-) Aber das war rein rethorisch gefragt, da die meisten doch sowieso die Quadrilliarde als letzte Zahl kennen.
:-)
Uebrigens wird im allgemeinen Sprachgebrauch nicht mehr als Milliarde benutzt. Das naechstehoehere bezeichnet man dann schon als Tausend-Milliarde. Vielleicht der Vorstellung wegen.
Nun ja, die Erfahrung habe ich noch nicht gemacht, daß jemand "tausend Milliarden" sagt... zumal unsereiner natürlich weiß, daß Bill Gates "billionair" (nicht zu verwechseln mit dem Billionär *g*) ist :-)
:-) GOGOOL klingt wirklich cool. Ich glaub das mit den Atomen war sogar untertrieben. Meines Wissen waren sogar Teilchen. Aber es reicht wohl, wenn es Uununununvorstellbar ist :-)
Du magst recht haben, ich habe auch einen Moment überlegt. Letztlich ist es aber für uns uninteressant, zumal ich in diesem Zusammenhang öfter den Bereich "10^80 bis 10^81" höre... und das deckt ungefähr den Unterschied Atome <-> Teilchen ab ;-)
Eine Zahl mit 10^100 Ziffern (also 10^(10^100)) heißt übrigens gogoolplex... :-)
<menschelei>Klingt fast noch schoener :-) Sollten wir nicht gleich wieder aus dem Sprachgebrauch des Forums verbannen :-)</menschelei>
Finde ich auch :-)
Dieses Forum kann ich übrigens zu GOGOOLPLEX Prozent empfehlen ;-)))
Die Funktion num2string überlasse ich Dir ;-)
Mir nicht, aber Boris machts sicher zuende. Hab gerade garkein Nerv dafuer.
Ging mir genauso ;-) vor allem, weil es ein bißchen mit Ausprobieren ist.
Cheatah
Hallo Boris,
das ist mal wieder so ein Thread - klare Aufgabenstellung, keine klaren Antworten. Weil mich das Thema interessiert hat, hab ich mal eine Routine geschrieben, die so was macht. Leider hat sie bei Zahlen ueber 100000 noch einen Fehler, deshalb bin ich da noch nicht weitergekommen. Auch ist sie ziemlich umstaendlich programmiert - aber im Gegensatz zu den bisherigen Antworten wenigstens eine Diskussionsgrundlage <g>. Also:
#!/usr/bin/perl
$Zahl = $ENV{'QUERY_STRING'};
$x = &Ganzzahl_in_Worten($Zahl);
print "Content-type: text/html\n\n";
print "<html><body>\n";
print "<font size=5>$Zahl = $x</font>\n";
print "</body></html>\n";
sub Ganzzahl_in_Worten
{
@EElems = ("","eins","zwei","drei","vier","fünf","sechs","sieben","acht","neun","zehn","elf","zwölf","dreizehn","vierzehn","fünfzehn","sechzehn","siebzehn","achtzehn","neunzehn","null");
@ZElems = ("und","ein","zwanzig","dreißig","vierzig","fünfzig","sechzig","siebzig","achtzig","neunzig","hundert");
@PElems = ("ein","hundert","tausend","millionen");
$Input = $_[0];
$Input =~ s/.//g;
($Zahl,$Rest) = split(/,/,$Input);
if($Zahl < 10) {
if($Zahl == 0) {
$Output = $EElems[-1];
return($Output);
}
else {
$Output = $EElems[$Zahl];
return($Output);
}
}
$Output = &Zehner($Zahl);
if($Zahl < 100) {
return($Output);
}
$Hunderter = substr($Zahl,length($Zahl)-3,1);
if($Hunderter == 1) {
$Output = $PElems[0].$PElems[1].$Output;
}
else {
$Output = $EElems[$Hunderter].$PElems[1].$Output;
}
if($Zahl < 1000) {
return($Output);
}
if($Zahl % 1000 == 0) {
$Output = "";
}
if($Zahl < 10000) {
$Tausender = substr($Zahl,length($Zahl)-4,1);
if($Tausender == 1) {
$Output = $PElems[0].$PElems[2].$Output;
return($Output);
}
else {
$Output = $EElems[$Tausender].$PElems[2].$Output;
return($Output);
}
}
$ZTausender = substr($Zahl,length($Zahl)-5,2);
$Zehntausender = &Zehner($ZTausender);
if($Zahl < 100000) {
$Output = $Zehntausender.$PElems[2].$Output;
return($Output);
}
if($Zahl < 1000000) {
$HTausender = substr($Zahl,length($Zahl)-6,1);
if($HTausender == 1) {
# HIER FOLGT DER FEHLER: $Zehntausender WIRD PLOETZLICH FALSCH INTERPRETIERT
$Output = $PElems[0].$PElems[1].$Zehntausender.$PElems[2].$Output;
return($Output);
}
else {
$Output = $EElems[$HTausender].$PElems[1].$Zehntausender.$PElems[2].$Output;
return($Output);
}
}
return($Output);
}
sub Zehner {
$ZInput = $_[0];
if($ZInput > 9 && $ZInput < 20) {
$Result = $EElems[$ZInput];
return($Result);
}
else {
$Einer = substr($Input,length($ZInput)-1,1);
$Zehner = substr($Input,length($ZInput)-2,1);
if($Einer == 1) {
$Result = $ZElems[1].$ZElems[0].$ZElems[$Zehner];
}
elsif($Zehner == 0) {
$Result = $EElems[$Einer];
}
else {
$Result = $EElems[$Einer].$ZElems[0].$ZElems[$Zehner];
}
}
return($Result);
}
Probier das mal mit Betraegen unter 100000 - dann sollte es prima funktionieren. Bei Betraegen zwischen 100000 und 1000000 verheddert er sich ploetzlich mit den Zehntausendern - obwohl die vorher bereits rechtzeitig in einer Variablen gespeichert wurden. Ich kam da einfach nicht weiter - vielleicht ist es ein Integer-Ueberlaufproblem oder so was.
viele Gruesse
Stefan Muenz
Hallo Boris,
das ist mal wieder so ein Thread - klare Aufgabenstellung, keine klaren Antworten. Weil mich das Thema interessiert hat, hab ich mal eine Routine geschrieben, die so was macht. Leider hat sie bei Zahlen ueber 100000 noch einen Fehler, deshalb bin ich da noch nicht weitergekommen. Auch ist sie ziemlich umstaendlich programmiert - aber im Gegensatz zu den bisherigen Antworten wenigstens eine Diskussionsgrundlage <g>. Also:
Hallo Stefan, hallo an dieser Programmierung Interessierte,
danke erstmal für die Grundlage auf meine Frage hin :).
Hintergrund ist der Versuch, die automatische Generierung eines Wechselformulars zu programmieren.
Der Wechsel wird im kaufmännischen Verkehr verwendet, aber ist sehr formstreng (verliert daher an Bedeutung, wegen der Angst einen Fehler zu machen ...) - ist aber aus kaufmännischer Sicht ein gutes Instrumetarium. Die (rechtssichere ;) Erstellung eines
Wechsels über HTML/P.E.R.L. könnte zu einer kleinen
Wiedergeburt führen, da auch so im Zweifel z.B. kleine GmbH's über ihre Haftungssumme hinaus beliefert werden können, wenn der Bezogene eine natürliche, damit prinzipiell nicht haftungsbeschränkte Person ist.
Nach der Formstrenge ist die Wechselsumme in Ziffern und Buchstaben anzugeben. Das zum Hintergrund.
Auf der anderen Seite sind unter "modularen" Gesichtspunkten andere Anwendungsfelder für die 'Übersetzung' nicht ausgeschlossen.
Auf jeden Fall interessant ;)
Ich versuche jetzt mal das script zu verstehen, was mir aber bislang auffällt ist:
Bislang 'packt' das Script auch unter 100.000,00 die 11-20er nicht richtig. Mehr dazu im nächsten posting ...
Bis dann
CU
Bo
#!/usr/bin/perl
Scriptname: betrag.pl
Scriptaufruf in URL-Zeile (Beispiel): http://127.0.0.1/cgi-bin/betrag.pl?71234,00
$Zahl = $ENV{'QUERY_STRING'};
$x = &Ganzzahl_in_Worten($Zahl);Test (HTML-Output / CGI)
print "Content-type: text/html\n\n";
print "<html><body>\n";
print "<font size=5>$Zahl = $x</font>\n";
print "</body></html>\n";sub Ganzzahl_in_Worten
{
@EElems = ("","eins","zwei","drei","vier","fünf","sechs","sieben","acht","neun","zehn","elf","zwölf","dreizehn","vierzehn","fünfzehn","sechzehn","siebzehn","achtzehn","neunzehn","null");
@ZElems = ("und","ein","zwanzig","dreißig","vierzig","fünfzig","sechzig","siebzig","achtzig","neunzig","hundert");
@PElems = ("ein","hundert","tausend","millionen");
$Input = $_[0];
$Input =~ s/.//g;
($Zahl,$Rest) = split(/,/,$Input);
if($Zahl < 10) {
if($Zahl == 0) {
$Output = $EElems[-1];
return($Output);
»» }
»» else {
$Output = $EElems[$Zahl];
return($Output);
»» }
}
$Output = &Zehner($Zahl);
if($Zahl < 100) {
return($Output);
}
$Hunderter = substr($Zahl,length($Zahl)-3,1);
if($Hunderter == 1) {
$Output = $PElems[0].$PElems[1].$Output;
}
else {
$Output = $EElems[$Hunderter].$PElems[1].$Output;
}
if($Zahl < 1000) {
return($Output);
}
if($Zahl % 1000 == 0) {
»» $Output = "";
}
if($Zahl < 10000) {
$Tausender = substr($Zahl,length($Zahl)-4,1);
if($Tausender == 1) {
$Output = $PElems[0].$PElems[2].$Output;
return($Output);
}
else {
$Output = $EElems[$Tausender].$PElems[2].$Output;
return($Output);
}
}
$ZTausender = substr($Zahl,length($Zahl)-5,2);
$Zehntausender = &Zehner($ZTausender);
if($Zahl < 100000) {
$Output = $Zehntausender.$PElems[2].$Output;
return($Output);
}
if($Zahl < 1000000) {
$HTausender = substr($Zahl,length($Zahl)-6,1);
if($HTausender == 1) {
# HIER FOLGT DER FEHLER: $Zehntausender WIRD PLOETZLICH FALSCH INTERPRETIERT
$Output = $PElems[0].$PElems[1].$Zehntausender.$PElems[2].$Output;
return($Output);
}
else {
$Output = $EElems[$HTausender].$PElems[1].$Zehntausender.$PElems[2].$Output;
return($Output);
}
}
return($Output);
}sub Zehner {
$ZInput = $_[0];
if($ZInput > 9 && $ZInput < 20) {
$Result = $EElems[$ZInput];
»» return($Result);
}
else {
$Einer = substr($Input,length($ZInput)-1,1);
$Zehner = substr($Input,length($ZInput)-2,1);
if($Einer == 1) {
$Result = $ZElems[1].$ZElems[0].$ZElems[$Zehner];
»» }
elsif($Zehner == 0) {
$Result = $EElems[$Einer];
»» }
else {
$Result = $EElems[$Einer].$ZElems[0].$ZElems[$Zehner];
»» }
}
return($Result);
}END
Probier das mal mit Betraegen unter 100000 - dann sollte es prima funktionieren. Bei Betraegen zwischen 100000 und 1000000 verheddert er sich ploetzlich mit den Zehntausendern - obwohl die vorher bereits rechtzeitig in einer Variablen gespeichert wurden. Ich kam da einfach nicht weiter - vielleicht ist es ein Integer-Ueberlaufproblem oder so was.
viele Gruesse
Stefan Muenz
Hallo zusammen,
habe mal in VB für Excel eine solche Funktion geschrieben, die der obigen Übersetzung stark ähnelt :)
Der Zehntausenderfehler ist dort an sich ausgebügelt, wenn es trotzdem irgendwo hakt meldet euch nochmal, Ihr müßt sie jetzt einfach nochmal übersetzen.
Function Zahlwort(zahl)
Dim a, b, c, hunderter(5) As String, zehner(5) As String, hilfezahl(3)
a = Array("null", "ein", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", _
"elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn")
b = Array("zehn", "zwanzig", "dreißzig", "vierzig", "fünfzig", "sechszig", "siebzig", "achtzig", "neunzig")
c = Array("null", "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun")
x = 1
y = 1
If zahl < 0 Then
vorzeichen = "minus"
zahl = Right(zahl, Len(zahl) - 1)
End If
If zahl Like "*,*" Then
komzahl = Right(zahl, Len(zahl) - InStr(zahl, ","))
For h = 1 To Len(komzahl)
nachkom = nachkom & c(Left(komzahl, 1))
komzahl = Right(komzahl, Len(komzahl) - 1)
Next h
komma = "komma"
zahl = Fix(zahl)
End If
If zahl = 0 Then
Zahlwort = vorzeichen & "null" & komma & nachkom
Exit Function
End If
If zahl = 1 Then
Zahlwort = vorzeichen & "eins" & komma & nachkom
Exit Function
End If
If zahl > 999 And zahl < 1000000 Then
tausend = "tausend"
hilfezahl(2) = Right(zahl, 3)
If hilfezahl(2) < 100 Then hilfezahl(2) = CInt(hilfezahl(2))
zahl = Left(zahl, Len(zahl) - 3)
x = 3
y = 2
End If
If zahl > 999999 Then
Millionen = "million"
hilfezahl(1) = Right(zahl, 6)
hilfezahl(2) = Right(zahl, 3)
If hilfezahl(2) < 100 Then hilfezahl(2) = CInt(hilfezahl(2))
zahl = Left(zahl, Len(zahl) - 6)
If zahl <> 1 Then Millionen = "millionen"
x = 3
End If
For i = y To x
If Len(zahl) > 3 Then
zahl = Left(zahl, 3)
If zahl < 100 Then zahl = CInt(zahl)
If zahl <> 0 Then tausend = "tausend"
End If
If zahl > 99 And Right(zahl, 2) = 0 Then
hunderter(i) = a(Left(zahl, 1)) & "hundert"
End If
If zahl > 99 Then
hunderter(i) = a(Left(zahl, 1)) & "hundert"
zahl = zahl - Left(zahl, 1) * 100
End If
If zahl < 100 And zahl > 19 And Right(zahl, 2) > 0 Then
If Right(zahl, 1) = 0 Then
zehner(i) = b(Left(zahl, 1) - 1)
Else
zehner(i) = "und" & b(Left(zahl, 1) - 1)
zahl = zahl - Left(zahl, 1) * 10
End If
End If
If zahl < 20 And zahl > 0 Then
zehner(i) = a(zahl) & zehner(i)
End If
zahl = hilfezahl(i)
Next i
Zahlwort = vorzeichen & hunderter(1) & zehner(1) & Millionen & hunderter(2) & zehner(2) & tausend & hunderter(3) & zehner(3) & komma & nachkom
If komma <> "" Then
If Right(Left(Zahlwort, InStr(Zahlwort, "k") - 1), 3) = "ein" Then Zahlwort = Left(Zahlwort, InStr(Zahlwort, "k") - 4) & "undeins" & Right(Zahlwort, Len(Zahlwort) - InStr(Zahlwort, "k") + 1)
ElseIf komma = "" Then
If Right(Zahlwort, 3) = "ein" Then Zahlwort = Left(Zahlwort, Len(Zahlwort) - 3) & "undeins"
End If
If Right(Left(Zahlwort, 4 + Len(vorzeichen)), 4) = "einm" Then Zahlwort = vorzeichen & "einem" & Right(Zahlwort, Len(Zahlwort) - 4 - Len(vorzeichen))
End Function
Gruß
Holger