Hab mich mal dran verkünstelt:
Man könnte auch noch was mit mit Runden, oder mit Nachkommastellen machen.
Ich denke aber, das sollte man eher als abgetrennte Funktion angehen. Etwa Runden hat ja nichts mit Zahlworten zu tun, und wenn man tatsächlich die Cents auf dem Scheck aufführen will, kann man die 2 Nachkommastellen ja nochmal extra durchlaufen lassen.
Am Algo-Konzept hat mich überrascht, wie systematisch die Grammatik eiglich ist, und insbesondere rekursiv: Die Regeln für milliardener, millionener, tausender, hunderter sind immer dieselben.
Und das unregelmäßige Zeugs im Bereich unter hundert wiederholt sich - absolut regelmäßig - auf den höheren Ebenen - Rekursion eben.
ZB um die Zahl
einhundertfünfundzwanzigmillioneneinhundertfünfundzwanzigtausendeinhundertfünfundzwanzig
Technisch gesehen setze ich v.a. 2 String-Arrays ein, und ein Array von anonymen Datentypen.
Auch verwende ich die weniger bekannte
Und
VB.NET-Quellcode
- Public Function NumberWord(n As Integer) As String
- Select Case n
- Case Is < Integer.MinValue + 2, Integer.MaxValue
- Throw New ArgumentOutOfRangeException("n", n, String.Format("valid range is: -{0} to {0}", Integer.MaxValue - 1))
- Case 0 : Return "null"
- Case Is < 0 : Return "minus " & NumberWord(-n)
- End Select
- NumberWord = NumberWordRecursive(n)
- Dim zehner, einer As Integer
- zehner = Math.DivRem(n, 10, einer)
- ' "s" anhängen, wenn keine zehner-stelle, und einer = 1 - zB 1, 101, 1001, 2501 ...
- If (zehner Mod 10) = 0 AndAlso einer = 1 Then NumberWord &= "s"
- End Function
- Private Function NumberWordRecursive(n As Integer) As String
- Dim einer = "##invalid ein zwei drei vier fünf sechs sieben acht neun zehn elf zwölf".Split
- Dim zehner = "##invalid zehn zwanzig dreißig vierzig fünfzig sechzig siebzig achzig neunzig".Split
- Dim dimension = {New With {.n = 100, .text = "##invalid"},
- New With {.n = 1000, .text = "hundert"},
- New With {.n = 1000000, .text = "tausend"},
- New With {.n = 1000000000, .text = "millionen"},
- New With {.n = Integer.MaxValue, .text = "milliarden"}}
- Dim geteilt, rest As Integer
- geteilt = Math.DivRem(n, 10, rest)
- Select Case n
- Case 0 : Return ""
- Case Is < 13 : Return einer(n)
- Case Is < 20 : Return einer(rest) & zehner(1)
- Case Is < 100
- If rest = 0 Then Return zehner(geteilt)
- 'wenn Einer da sind, vertauschte Reihenfolge
- Return einer(rest) & "und" & zehner(geteilt)
- Case Else
- Dim i = Array.FindIndex(dimension, Function(itm) n < itm.n)
- geteilt = Math.DivRem(n, dimension(i - 1).n, rest)
- NumberWordRecursive = NumberWordRecursive(geteilt) & dimension(i).text & NumberWordRecursive(rest)
- If i > 2 AndAlso geteilt = 1 Then
- Select Case i 'singular bei millionen/milliarden
- Case 3
- NumberWordRecursive = NumberWordRecursive.Remove(10, 2).Insert(3, "e")
- Case 4
- NumberWordRecursive = NumberWordRecursive.Remove(12, 1).Insert(3, "e")
- End Select
- End If
- End Select
- End Function
- Private Sub Test()
- ' paar interessante Zahlen
- For Each i In {0, 1, 125, 1000000, 1000000000, 1000100000, 100010000, 101001, 1021, 3333, 1123456, 3123456, Integer.MaxValue - 1}
- Console.WriteLine(NumberWord(i))
- Next
- End
- End Sub
Ich denke aber, das sollte man eher als abgetrennte Funktion angehen. Etwa Runden hat ja nichts mit Zahlworten zu tun, und wenn man tatsächlich die Cents auf dem Scheck aufführen will, kann man die 2 Nachkommastellen ja nochmal extra durchlaufen lassen.
Am Algo-Konzept hat mich überrascht, wie systematisch die Grammatik eiglich ist, und insbesondere rekursiv: Die Regeln für milliardener, millionener, tausender, hunderter sind immer dieselben.
Und das unregelmäßige Zeugs im Bereich unter hundert wiederholt sich - absolut regelmäßig - auf den höheren Ebenen - Rekursion eben.
ZB um die Zahl
125125125
zu "sagen", wird das Wort "einhundertfünfundzwanzig" drei mal gebildet, und es wird halt "millionen" und "tausend" eingefügt:einhundertfünfundzwanzigmillioneneinhundertfünfundzwanzigtausendeinhundertfünfundzwanzig
Technisch gesehen setze ich v.a. 2 String-Arrays ein, und ein Array von anonymen Datentypen.
Auch verwende ich die weniger bekannte
Math.DivRem()
- Methode, eine Art mächtigeres Modulo, weils den Rest der Teilung nicht verfallen lässt.Und
Array.FindIndex()
mit anonymer Methode - kennen vmtl. auch nur Leute, die gelegentlich browsen im Framework - mittm ObjectBrowser Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()