Autor Beitrag
DocSol
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Do 03.09.09 19:25 
Hallo,

ich habe heute in der Schule die Aufgabe bekommen, ein Programm zu schreiben, welches ausgeschriebene Zahlen erkennt und in Dezimalwerte umwandelt...

Als Beispiel sei gennant:
Eine eingegebene "zwölf" soll vom Programm erkannt und in einer "12" umgewandelt werden. Oder auch eine "zweihundertdreiundvierzig" in eine "243".

Die Zahlen werden in ein Edit-Feld eingegeben und auf Knopfdruck sollen diese umgewandelt werden.

Gibt es da eine fertige Funktion für?

Danke schonmal für eure Hilfe.


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Do 03.09.2009 um 19:30
Webo
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 577
Erhaltene Danke: 14

Win 7, Debian
C# (Visual Studio 2013), PHP, C, C++ (Eclipse, KDevelop)
BeitragVerfasst: Do 03.09.09 19:55 
Nein, sofern ich weiss, gibt es dafür keine fertige Funktion. Doch:
Dies ist zwar die Umgekehrte Funktion, aber vllt. hilft sie dir ja, damit du den richtigen Gedankenblitz bekommst, wie du sowas realisieren könntest ...

_________________
Man kann nur das aus dem Ärmel schütteln, was man auch vorher reingesteckt hat.
Marc.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1876
Erhaltene Danke: 129

Win 8.1, Xubuntu 15.10

BeitragVerfasst: Do 03.09.09 20:03 
user profile iconWebo hat folgendes geschrieben Zum zitierten Posting springen:
Nein, sofern ich weiss, gibt es dafür keine fertige Funktion. Doch:
Dies ist zwar die Umgekehrte Funktion, aber vllt. hilft sie dir ja, damit du den richtigen Gedankenblitz bekommst, wie du sowas realisieren könntest ...

Schließ mich dort an. Alternativ gibt's noch eine "Umgekehrte"-Funktion in der DP: http://www.delphipraxis.net/topic88367.html.

Grüße,
Marc
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Do 03.09.09 20:38 
Hallo,

erstmal :welcome: in der EE.

eine fertige Funktion gibt es bestimmt irgendwo,
aber was nützt Dir die Funktion wenn Du den Code dann nicht erklären kannst. :wink:

- String zerlegen(! in 'hundert' ist auch ein 'und' enthalten !)
zweihundertvierundvierzig = > 'zwei' 'hundert' 'vier' 'und' 'vier' 'zig'
eintausendundelf => 'ein' 'tausend' 'und' 'elf'

- in Zahlen/Multiplikatoren umwandeln(! 'zwan' ist auch eine 2 in 'zwanzig' !)
zweihundertvierundvierzig
'zwei' -> 2
'hundert' -> * 100
'vier' -> 4
'und' -> +
'vier' -> 4
'zig' -> *10

eintausendunddreißig
'ein' -> 1
'tausend' * 1000
'und' -> +
'drei' -> 3
'ßig' * 10

- rechnen
überlass ich jetzt Dir :angel:

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Fr 04.09.09 18:03 
Hallo und danke schonmal für die nützlichen Tipps. Ich habe mir schonmal die umgekehrten Funktionen etwas angesehen. Ich hoffe, es wird nicht allzu kompliziert, diese Funktionen umzumodeln...

Mit "fertige Funktion" meinte ich eher etwas, was bei Delphi schon mit dabei ist... so ne Art StrToInt halt nur für die Wörter :D

Ich werd mal einfach schauen, wie weit ich da komme.
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: Fr 04.09.09 18:30 
wär ja etwas witzlos von deinem lehrer sowas zu verlangen und dann gibts das schon in delphi. ;)

außerdem: Codegear müsste dann für jede sprache dieser welt diese Funktion implementieren und das wäre dann doch etwas mühsam ;) außerdem müsste die funktion dann noch automatisch die sprache erkennen, nem? ;)

lg elundril

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Sa 05.09.09 12:16 
Ja da hast du wohl recht.
Momentan verzweifel ich aber eher daran, meine ausgeschriebene Zahl zu zerlegen... Mit Pos und Copy komme ich da irgendwie nicht weiter.
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: Sa 05.09.09 12:24 
also ich würd es so machen, das ich mir zuerst die milliarde suche, dann alles inklusive dem milliarde aus dem ding rausschneide. dann hab ich vor dem milliarde ne zahl stehen, die mir angibt, wieviele milliarden ich hab, usw. ;)

lg elundril

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Sa 05.09.09 12:53 
Ja genau ich wollte es so machen, wie Lannes es beschrieben hat. Aber wenn ich z.B. die erste Stelle suche (ich fange mal klein an mit der 'einhundert') habe ich das Problem, dass er mir nicht die 'ein' ausgibt.

Mal zur Veranschaulichung:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
try
    Result := StrToInt(zeile);
  except
    on EConvertError do
    begin
      for apos := 1 to length(zeile) do
      begin
        if (zeile[apos] = 'ein'OR (zeile[apos] = 'eins'OR (zeile[apos] = 'eine')then
          break
        else
          thilf := thilf + zeile[apos];
      end;
    end;
  end;


Ich möchte in thilf nun also nur ein, eins oder eine stehen haben damit ich diese dann konvertieren kann zur 1...

Aber er gibt mir immer die 'einhundert' aus...
platzwart
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1054
Erhaltene Danke: 78

Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
BeitragVerfasst: Sa 05.09.09 13:02 
user profile iconDocSol hat folgendes geschrieben Zum zitierten Posting springen:

Mal zur Veranschaulichung:
ausblenden Delphi-Quelltext
1:
 if (zeile[apos] = 'ein'OR (zeile[apos] = 'eins'OR (zeile[apos] = 'eine')then					


Ich möchte in thilf nun also nur ein, eins oder eine stehen haben damit ich diese dann konvertieren kann zur 1...

Aber er gibt mir immer die 'einhundert' aus...



Kein Wunder, denn zeile[apos] ist nur ein Zeichen! Wenn apos=1 dann ist es das erste Zeichen, apos=2 das zweite etc. Du vergleichst aber immer mit einem String wie 'ein' und das geht dann natürlich schief...

_________________
Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Sa 05.09.09 13:06 
Und wie kann ich dann am Besten den String nach 'ein', 'eins' oder 'eine' durchsuchen?
Ich stehe da momentan echt toal auf dem Schlach und komme nicht voran...
platzwart
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1054
Erhaltene Danke: 78

Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
BeitragVerfasst: Sa 05.09.09 13:08 
ausblenden Delphi-Quelltext
1:
If(Pos(Zeichenkette, 'ein')>0)then vorhanden else nicht vorhanden;					

_________________
Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Sa 05.09.09 13:51 
Danke für deine Hilfe...

Ich habe mir nun einen weiteren Lösungsansatz überlegt bzw. mir wurde so etwas vorgeschlagen:

Ich durchsuche die ausgeschriebene Zahl zuerst nach den "Punkten" d.h. durchsuche den String nach 'millionen' und 'tausend'.
Die Zahl, die dann z.B. vor dem 'millionen' steht, konvertiere ich und multipliziere sie später einfach mit 1.000.000

Dafür habe ich mir dann folgendes ausgedacht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
if (Pos(zeile, 'millionen') > 0then
begin 
  mwert := Copy(zeile,0,Pos(zeile, 'millionen')-1);
  zeile := Copy(zeile,Pos(zeile, 'millionen')+8,length(zeile);
end;

Den Quellcode habe ich eben schnell aus dem Kopf geschrieben...

Wenn ich jetzt nicht total daneben liege, müsste ich in "mwert" dann den Millionenwert haben, den ich mit 1.000.000 multiplizieren kann und in "zeile" müsste der Rest der verbleibenden Zahl stehen (also die Zahl ab der Tausenderstelle) oder?
Mal als Beispiel mit der Zahl "dreihundertzwölfmillionenvierundachtzigtausendeinhundertundzwei" (312.084.102)

In der Variable "mwert" steht dann doch : "dreihundertzwölf"
und in "zeile" : "vierundachtzigtausendeinhundertundzwei"


Und genauso würde ich dann auch die Tausenderzahl "ausschneiden"...
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Sa 05.09.09 16:58 
Also ich würde da ja so herangehen:
-> "eins" in "ein" und dann "ein" in "eins" umwandeln.
-> Danach (ich weiß, ist nicht EBNF):
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
einer = (eins, zwei, drei, vier, fünf, sechs, sieben, acht, neun)
zehnfach = (zehn, zwanzig, dreisig, vierzig, fünfzig, sechzig, siebzig, achzig, neunzig)
irrzehn = (elf, zwölf, dreizehn, vierzehn, fünfzehn, sechzehn, siebzehn, achzehn, neunzehn)
zehner = zehner | irrzehn | einer+"und"+zehner
hunderfach = einer+"hundert" | "hundert"
hunderter = hundertfach + zehner | hundertfach + einer
...


Mit entsprechenden Methoden IstZehner() usw. sollte das eigentlich gehen.
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Sa 05.09.09 18:31 
Jakob ist dieser Lösungsvorschlag nicht eher dafür gedacht, aus Integerwerten ausgeschriebene Zahlen zu erstellen? So verstehe ich das jedenfalls...

Woran genau kann es eigentlich liegen, wenn ich mit dem 'Pos' Befehl innerhalb meines String das gesuchte Wort nicht finde?
Ich habe z.B. die Zahl "einemillionen" und suche mit 'Pos' nach der Zeichenfolge "millionen". Die wird allerdings nicht gefunden.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
if (Pos(zeile, 'millionen') > 0then
begin
  ShowMessage('Es sind Millionen vorhanden');
  break;
end;


So siehts aus... Das 'break;' ist nur für mich da, muss also nicht beachtet werden.
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Sa 05.09.09 19:35 
Hallo,

bist Du Dir sicher das Du "einemillionen" in Deinem zu durchsuchenden String hast?
Richtig geschrieben ist das:
eine Million
zwei Millionen

:arrow: Erst nach "millionen" suchen, dann nach "million"

Dein anderes Beispiel kann auch unterschiedlich geschrieben sein
"dreihundertzwölfmillionenvierundachtzigtausendeinhundertundzwei"
"dreihundertzwölf Millionen vierundachtzigtausendeinhundertzwei"
Laut Rechtschreibung werden ausgeschriebene Zahlen gößer 1.000.000 durch Leerzeichen getrennt.

Z.B. kann auch die Zahl 1987 in mehreren Varianten geschrieben sein:
eintausendneunhundertsiebenundachtzig
neunzehnhundertundsiebenundachtzig
neunzehnhundertsiebenundachtzig

Noch ein schönes Beispiel:
Duden: dreißig
aus dem Code vom Delphi-treff: dreisig
falsch geschrieben dreissig

oder wie ist es mit Umlauten
"zwölf" ist eindeutig
"zwoelf" = "zwo" und "elf"

Sind die zu verarbeitenden Zahlenstrings eindeutig oder soll Dein Programm auch solche Probleme abfangen?

Also zuerst die eindeutigen, wie schon bei der "million(en)" zuerst suchen und dann die Reststrings weiter splitten:
zwoelftausendelf
zwoelf tausendelf
zwoelf tausend elf

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
DocSol Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Sa 05.09.09 20:17 
In den Beispielen, die bei der Aufgabenstellung dabei waren, wurden die ausgeschriebenen Zahlen zusammen geschrieben. Und ich habe in meinem String zum Testen sogar nur "einemillionen" stehen gehabt. Dennoch wurde das "millionen" nicht gefunden. Wenn ich jedoch nur das Wort "millionen" im String habe, wird es gefunden.

Ich gehe von eindeutigen Zahlenstrings aus. Also "dreihundertzwölfmillionenvierundachtzigtausendeinhundertundzwei" (mit UND) usw...

Ä, Ü und Ö gehen auch.

Zahlen wie 1987 (Neunzehnhundertsiebenundachtzig) gibt es nicht... es ist also "Eintausendneunhundertsiebenundachtzig"

Wie schon erwähnt, klappt das Suchen mit Pos nicht so, wie ich es gerne hätte... also obwohl im String das wort "millionen" vorkommt, wird es nicht gefunden.
Splitten werde ich diesen String dann in unterschiedliche Variablen, mit denen ich weiter arbeite.
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Sa 05.09.09 21:08 
dein Problem könnte groß und kleinschreibung sein, wandle den String vorher mal mit s := lowercase(s:String); um.

Dein Programm sollte neunzehnhundertundneunundneunzig eh erkennen da:

neun
* zehn
* hundert
+ (und) neun
+ (und) neun
* (zig) 10

= 1999

Achtung: dabei ist es Wichtig, dass du das zig nur auf die neun und nicht auf den Rest anwendest.

Meine allgmeine Vorgehensweise wäre also ungefähr:


Man beginnt immer mit der Zahl 1, es sei denn, das Wort beginnt mit:

"zwei"
"drei"
"vier"
...
"zwölf"

danach folgt eig. immer

"zig"
"hundert"
"tausend"
"millionen"
etc.

welches dann entsprechend multipliziert, oder bei

"zehn"

addiert wird, bzw. bei

"und"

eine Addition einleitet.
ich überlege gerade, ob man das nicht evtl. Rekursiv lösen könnte...

Man könnte sozusagen eine "expect"-Funktion einbauen, die diese Regeln "beherrscht", und beschließt, was als nächstes kommt.
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: So 06.09.09 00:26 
Hallo,
user profile iconFinnO hat folgendes geschrieben Zum zitierten Posting springen:

Man beginnt immer mit der Zahl 1, es sei denn, das Wort beginnt mit:

"zwei"
"drei"
"vier"
...
"zwölf"

danach folgt eig. immer

"zig"
eigentlich, da bleiben dann aber noch so ca. siebenzig Ausnahmen :mrgreen:


user profile iconFinnO hat folgendes geschrieben Zum zitierten Posting springen:
ich überlege gerade, ob man das nicht evtl. Rekursiv lösen könnte...
ja.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: So 06.09.09 10:41 
@ siebenzig: siebenzig würde ja auch funktionieren. Na und? Tatsache ist, das Programm wandelt alle Zahlen um, und welche, die keine sind, recht genau auch.

Generell sollte man aber lieber Zahlen wie "Sieben" vorher schon zu "sieb" verkürzen (genau wie "zwei" zu "zwo" usw.)