# B4J QuestionHow to read a number to word

#### universengo

##### Member
Hello friends!
I am a newbje, I need your help to show me about reading a number to word.
If you have this code, please share me
Example:
121 => One hundred and twenty one

#### Erel

##### B4X founder
Staff member
Longtime User
First 100 numbers:
B4X:
``````Sub Process_Globals
Private FirstTwenty() As String = Array As String("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", _
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty")
Private Tens() As String = Array As String("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety")
End Sub

Sub AppStart (Args() As String)
For i = 0 To 100
Log(NumberToWords(i))
Next
End Sub

Sub NumberToWords(n As Int) As String
If n >= 100 Then Return "too large"
If n <= 20 Then Return FirstTwenty(n)
Dim t1 As Int = Floor(n / 10)
Dim t0 As Int = n Mod 10
If t0 = 0 Then
Return Tens(t1)
End If
Return Tens(t1) & " " & FirstTwenty(t0)
End Sub``````

#### universengo

##### Member
First 100 numbers:
B4X:
``````Sub Process_Globals
Private FirstTwenty() As String = Array As String("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", _
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty")
Private Tens() As String = Array As String("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety")
End Sub

Sub AppStart (Args() As String)
For i = 0 To 100
Log(NumberToWords(i))
Next
End Sub

Sub NumberToWords(n As Int) As String
If n >= 100 Then Return "too large"
If n <= 20 Then Return FirstTwenty(n)
Dim t1 As Int = Floor(n / 10)
Dim t0 As Int = n Mod 10
If t0 = 0 Then
Return Tens(t1)
End If
Return Tens(t1) & " " & FirstTwenty(t0)
End Sub``````
Very good!
Thanks Erel so much!
Good luck to you!

#### emexes

##### Expert
Example:
121 => One hundred and twenty one
You'll be needing to extend Erel's code to make your example work. Something like this:
B4X:
``````Sub BiggerNumberToWords(X)

If X >= 5000 Then
Return "too large"
Else If X < -5000 Then
Return "too small"
End If

Dim PlusMinus As String = ""
If X < 0 Then
PlusMinus = "minus "    'note trailing space to separate from number
X = -X
End If

Dim Hundreds As String = ""
If X >= 100 Then
Hundreds = NumberToWords(Int(X / 100)) & " hundred"
End If

Dim Units As String = ""
If (X Mod 100) <> 0 Or X = 0 Then
Units = NumberToWords(X Mod 100)
End If

Dim Joiner As String = ""
If Hundreds.Length <> 0 And Units.Length <> 0 Then
Joiner = " and "
End If

Return PlusMinus & Hundreds & Joiner & Units

End Sub``````
Should work, but I haven't tested it. I remember from high school that numbers-to-words was not as easy as you'd first think. Especially in French, with their passion for number twenty.

Last edited:

#### universengo

##### Member
You'll be needing to extend Erel's code to make your example work. Something like this:
B4X:
``````Sub BiggerNumberToWords(X)

If X >= 5000 Then
Return "too large"
Else If X < -5000 Then
Return "too small"
End If

Dim PlusMinus As String = ""
If X < 0 Then
PlusMinus = "minus "    'note trailing space to separate from number
X = -X
End If

Dim Hundreds As String = ""
If X >= 100 Then
Hundreds = NumberToWords(Int(X / 100)) & " hundred"
End If

Dim Units As String = ""
If (X Mod 100) <> 0 Or X = 0 Then
Units = NumberToWords(X Mod 100)
End If

Dim Joiner As String = ""
If Hundreds.Length <> 0 And Units.Length <> 0 Then
Joiner = " and "
End If

Return PlusMinus & Hundreds & Joiner & Units

End Sub``````
Should work, but I haven't tested it. I remember from high school that this was not as easy as you'd first think. Especially in French, with their passion for number twenty.

Thanks emexes so much.
I am trying Erel's and your code now.
Now I know my way to work with this my question.

Your code is fix as sub'name (Sub BiggerNumberToWords(X) as string ) and delete int at "Int(X / 100))".
Perfect code:
B4X:
``````Sub BiggerNumberToWords(X) as string

If X >= 5000 Then
Return "too large"
Else If X < -5000 Then
Return "too small"
End If

Dim PlusMinus As String = ""
If X < 0 Then
PlusMinus = "minus "    'note trailing space to separate from number
X = -X
End If

Dim Hundreds As String = ""
If X >= 100 Then
Hundreds = NumberToWords(X / 100) & " hundred"
End If

Dim Units As String = ""
If (X Mod 100) <> 0 Or X = 0 Then
Units = NumberToWords(X Mod 100)
End If

Dim Joiner As String = ""
If Hundreds.Length <> 0 And Units.Length <> 0 Then
Joiner = " and "
End If

Return PlusMinus & Hundreds & Joiner & Units

End Sub``````

Last edited:

#### emexes

##### Expert
Mucking around during lunch break. Ideal for Green Bottles or Little Monkeys - test log is:
B4X:
``````1000000000000006 = One Quadrillion and Six green bottles, hanging on the wall
1000000000000005 = One Quadrillion and Five green bottles, hanging on the wall
1000000000000004 = One Quadrillion and Four green bottles, hanging on the wall
1000000000000003 = One Quadrillion and Three green bottles, hanging on the wall
1000000000000002 = One Quadrillion and Two green bottles, hanging on the wall
1000000000000001 = One Quadrillion and One green bottles, hanging on the wall
1000000000000000 = One Quadrillion green bottles, hanging on the wall
999999999999999 = Nine Hundred and Ninety-Nine Trillion, Nine Hundred and Ninety-Nine Billion, Nine Hundred and Ninety-Nine Million, Nine Hundred and Ninety-Nine Thousand, Nine Hundred and Ninety-Nine green bottles, hanging on the wall
999999999999998 = Nine Hundred and Ninety-Nine Trillion, Nine Hundred and Ninety-Nine Billion, Nine Hundred and Ninety-Nine Million, Nine Hundred and Ninety-Nine Thousand, Nine Hundred and Ninety-Eight green bottles, hanging on the wall
999999999999997 = Nine Hundred and Ninety-Nine Trillion, Nine Hundred and Ninety-Nine Billion, Nine Hundred and Ninety-Nine Million, Nine Hundred and Ninety-Nine Thousand, Nine Hundred and Ninety-Seven green bottles, hanging on the wall
999999999999996 = Nine Hundred and Ninety-Nine Trillion, Nine Hundred and Ninety-Nine Billion, Nine Hundred and Ninety-Nine Million, Nine Hundred and Ninety-Nine Thousand, Nine Hundred and Ninety-Six green bottles, hanging on the wall``````
from test code:
B4X:
``````Dim RoundAbout As Long = Power(10, 15)
Dim I As Long

For I = RoundAbout + 6 To RoundAbout - 4 Step -1
Log(I & " = " & NumberToWords(I) & " green bottles, hanging on the wall")
Next``````

Last edited:
• universengo, Erel and DonManfred

#### emexes

##### Expert
Static word lists are:
B4X:
``````Sub Process_Globals

Dim UnitWords() As String = Array As String( _
"", "One", "Two", "Three", "Four", _
"Five", "Six", "Seven", "Eight", "Nine", _
"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", _
"Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" _
)

Dim TenWords() As String = Array As String( _
"", "Ten", "Twenty", "Thirty", "Forty", _
"Fifty", "Sixty", "Seventy", "Eighty", "Ninety" _
)

'only need to go up to Pentillions to handle largest Long integer, but while we're here...
Dim ThousandWords() As String = Array As String( _
"", "Thousand", "Million", "Billion", "Trillion", _
"Quadrillion", "Pentillion", "Sexillion", "Septillion", "Octillion" _
)

End Sub``````
and the associated functions are:
B4X:
``````Sub NumberToWords(N As Long) As String

If N < 0 Then
Return "Minus " & NumberToWordsPositive(-N)
Else
Return NumberToWordsPositive(N)    'including zero
End If

End Sub

Sub NumberToWordsPositive(N As Long) As String

If N = 0 Then
Return "Zero"    'that gets rid of that pesky special case
End If

Dim GroupsOfThree(10) As Int

Dim NumGroupsOfThree As Int = 0

Do While N <> 0
GroupsOfThree(NumGroupsOfThree) = N Mod 1000
NumGroupsOfThree = NumGroupsOfThree + 1

N = N / 1000
Loop

Dim Temp As String = ""
For GroupOfThree = NumGroupsOfThree - 1 To 0 Step -1
Dim ThisGroup As Int = GroupsOfThree(GroupOfThree)

If ThisGroup <> 0 Then
If Temp.Length <> 0 Then
If GroupOfThree = 0 And ThisGroup < 100 Then
Temp = Temp & " and "
Else
Temp = Temp & ", "
End If
End If

Temp = Temp & NumberToWords1000(ThisGroup)

If GroupOfThree <> 0 Then
Temp = Temp & " " & ThousandWords(GroupOfThree)
End If
End If
Next

Return Temp

End Sub

Sub NumberToWords1000(N As Int) As String

If N < 100 Then
Return NumberToWords100(N)
End If

Dim Hundreds As String = UnitWords(N / 100) & " Hundred"    'Hundreds always non-blank since N < 100 already done
Dim TensUnits As String = NumberToWords100(N Mod 100)    'TensUnits could be blank if digits are 00

If TensUnits.Length = 0 Then
Return Hundreds
Else
Return Hundreds & " and " & TensUnits
End If

End Sub

Sub NumberToWords100(N As Int) As String

If N < 20 Then
Return UnitWords(N)
End If

Dim Tens As String = TenWords(N / 10)    'Tens always non-blank since N < 20 already done
Dim Units As String = UnitWords(N Mod 10)    'Units could be blank if digit is 0

If Units.Length = 0 Then
Return Tens
Else
Return Tens & "-" & Units
End If

End Sub``````

Last edited:

#### emexes

##### Expert
Your code is fix as sub'name (Sub BiggerNumberToWords(X) as string ) and delete int at "Int(X / 100))".
I'd like to say those were intentional errors, to check whether you're paying attention, but... nope.

Not bad for code banged out on the fly, though.
Perfect code
thanks to team effort • universengo

#### universengo

##### Member
Thanks for your help. I think this topic can be solved.

#### emexes

##### Expert
I think this topic can be solved.
Few things are ever fully solved ;-)

Enhancements that have occurred to me since are:

- select between British ("Four Hundred and Twenty") and American ("Four Hundred Twenty") styles
- year-style words eg Apollo 11 landing in nineteen sixty-nine, London Olympics in twenty twelve.
- billions in thousands-of-millions, eg twenty-five thousand million instead of twenty-five billion
- thousands in hundreds, eg, nineteen hundred and sixty-six instead of one thousand, nine hundred and sixty-six

• Erel and universengo