|
-
May 8th, 2011, 07:15 PM
#1
Thread Starter
Stack Overflow moderator
Number to text
This is my first cool project in a while Everybody always makes numbers-to-text functions some time, but this one goes up to sextillions (and could handle much more than that), has proper grammar, and does irreductible fractions for you!
Code:
Public Function ToWords(ByVal num As Decimal) As String
If num = 0 Then Return "Zero"
Dim illions() As String = {"m", "b", "tr", "quadr", "quint", "sext"} ', "sept", "oct", "non", "dec", "undec", "dodec"} 'Go farther if you want... but you'll have to change the numerical type.
Dim ties() As String = {"twen", "thir", "four", "fif", "six", "seven", "eight", "nine"}
Dim nums() As String = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}
Dim teens() As String = {"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}
Dim result As New System.Text.StringBuilder()
If num < 0 Then
result.Append("negative ")
num = -num
End If
'***illions first...
For i As Integer = illions.Length - 1 To 0 Step -1
'They always come in threes, starting with 1000000.
Dim d As Decimal = 1000
For x As Integer = 0 To i
d *= 1000
Next
Dim n As Integer = 0
While num >= d
n += 1
num -= d
End While
If n > 0 Then
result.Append(ToWords(n))
result.Append(" "c)
result.Append(illions(i))
result.Append("illion, ")
End If
Next
'Then, thousands
Dim thousands As Integer = 0
While num >= 1000
thousands += 1
num -= 1000
End While
If thousands > 0 Then
result.Append(ToWords(thousands))
result.Append(" thousand, ")
End If
'Hundreds
Dim hundreds As Integer = 0
While num >= 100
hundreds += 1
num -= 100
End While
If hundreds > 0 Then
result.Append(ToWords(hundreds))
result.Append(" hundred ")
End If
'Tens
If num >= 20 Then
result.Append(ties(CInt(Math.Floor(num / 10)) - 2))
result.Append("ty-")
num -= CInt(Math.Floor(num / 10)) * 10
End If
If num < 20 AndAlso num > 10 Then
result.Append(teens(CInt(Math.Floor(num - 10)) - 1))
result.Append(" "c)
num -= 10
End If
'Singles
If Math.Floor(num) > 0 Then
result.Append(nums(CInt(Math.Floor(num)) - 1))
result.Append(" "c)
num -= Math.Floor(num)
End If
'Now, the hard part - fractions.
If num > 0 Then
Dim numerator, denominator As Integer
If ToFraction(num, numerator, denominator) Then
result.Append("and ")
result.Append(ToWords(numerator))
result.Append(" "c)
Dim ths() As String = {"half", "third", "fourth", "fifth"}
Dim thp() As String = {"halves", "thirds", "fourths", "fifths"}
If denominator <= ths.Length + 1 Then
result.Append(If(numerator = 1, ths(denominator - 2), thp(denominator - 2)))
result.Append(" "c)
Else
result.Append(ToWords(denominator).Replace(" "c, "-"c)) 'Fourty-millionths, not fourty millionths.
result.Append("th")
If numerator > 1 Then result.Append("s"c)
result.Append(" "c)
End If
Else
result.Append("point ")
Do
num *= 10
result.Append(ToWords(Math.Floor(num)))
result.Append(" "c)
num -= Math.Floor(num)
Loop While num > 0
End If
End If
'Some final processing
result.Remove(result.Length - 1, 1)
If result(result.Length - 1) = ","c Then result.Remove(result.Length - 1, 1)
'Return the result
ToWords = result.ToString().ToLower()
ToWords = Char.ToUpper(ToWords.Chars(0)) & ToWords.Substring(1)
End Function
Public Function ToFraction(ByVal n As Decimal, ByRef numerator As Integer, ByRef denominator As Integer) As Boolean
Try
'We don't support 0.333333333333 = 1/3, unfortunately. :(
numerator = Integer.Parse(n.ToString().Substring(2))
denominator = CInt(10 ^ (n.ToString().Length - 2))
Dim tN As Integer = numerator
Dim tD As Integer = denominator
Dim nFactors As New List(Of Integer)
Dim dFactors As New List(Of Integer)
For d As Integer = 2 To numerator - 1
While tN Mod d = 0
nFactors.Add(d)
tN \= d
End While
Next
If nFactors.Count = 0 Then nFactors.Add(numerator)
For d As Integer = 2 To denominator - 1
While tD Mod d = 0
dFactors.Add(d)
tD \= d
End While
Next
If dFactors.Count = 0 Then dFactors.Add(denominator)
Dim i As Integer
While i < nFactors.Count
Dim j As Integer = dFactors.IndexOf(nFactors(i))
If j > -1 Then
dFactors.RemoveAt(j)
nFactors.RemoveAt(i)
Else
i += 1
End If
End While
numerator = nFactors.Aggregate(Function(m As Integer, o As Integer) m * o)
denominator = dFactors.Aggregate(Function(m As Integer, o As Integer) m * o)
Return True
Catch
Return False
End Try
End Function
Last edited by minitech; May 9th, 2011 at 02:42 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|