002_NumToText

A program that spells out numbers

Gisella Kontaria
codeZizzle
8 min readMay 11, 2020

--

In this project we will build a program that converts numbers into words. This will be practically useful in banks, where an amount of money should be printed in spelling when writing checks. Of course there are a lot of “Number to Words” engines that are available to use on the internet, but I guess it’d be fun to try to recreate it ourselves in Java!

Here Bryan and I will be making two different versions: Indonesian and English converters. The two languages will each have different number conventions and exceptions, hence our codes will be slightly different.

Gisella’s Converter (Indonesian)

Main method

Smallest building blocks in Java are called methods/functions. Every program will have a main () method, which is the first method that the IDE will execute. My main method will do three things in order: ask the user to input a number, analyze the amount of digits and add the extension -ribu or -juta where needed, and print the result on the user’s screen.

Main method

1) User Input

In our first few lines of code, we should first display “Insert amount:” in the user’s screen and ask them to input the numbers. This procedure can be accomplished using the print(“Insert amount: “) function and scanner reference that we have previously used in 001_MortgageCalculator. If the code is written correctly, the terminal should look like this:

Terminal

I will use the while(true) loop to allow the user to continually input and convert an amount without having to re-run the code. I will also have to add an if-statement that would render false to end/break this loop. In this case, the loop will break if a user inputs “0” (lines 8–9).

This converter will assume that the amount of money does not carry decimal points for simplicity — IDR also does not involve cents irl. Hence the primitive variable int is used to define amount that the user inputs as seen in line 7. It can be replaced with float when working with cents in dollars/other currencies, but we will deal not be dealing with that in this project.

2) Parameters

The next step would be setting parameters/conditions to count the number of digits in amount. It would then allow the program to know where to add the words “juta” or “ribu” when necessary.

This can be done using the number.length() function from the String class. Computers, however, cannot analyze numbers in int format when the function is part of a String class; amount should first be converted into a String (line 10). Therefore we covert amount to number using the function Integer.toString(amount). I then define the int i as the length (number of digits) of number.

Next, I parsed i into groups of 3 digits by grouping them into arrays. If i>3, input should be either in ribu or juta. By using the while() loop again, the parsing will continue until i is not greater than 3. In order to achieve this, for each successive loop, the amount of digits is subtracted by 3 (i-3). For example:

number (user’s input) = 1760980

Loop 1

i = 7 (while i>3=true)

arrayNumber: {“980”, “”, “”}

positionArray: 1

i-3 = 4

Loop 2

i=4 (while i>3=true)

arrayNumber: {“980”, “760”, “”}

i-3 = 1

positionArray: 2

Loop 3

i = 1 (while i>3=false)

Now that we are out of the while loop, the program will continue to line 19. From this point onwards, we will create new for and if statements that aim to spell out the numbers in arrayNumber and add “Juta” and “Ribu” extensions where necessary.

Referring to the example above, currently arrayNumber is {“980”, “760”, “”}. To add “1” from “1760980” into the last slot, we use the function number.substring(0,i) in line 19. This function will ask the program to take the digit in 0th position (computer starts counting from 0) up until i. As i is 1 from Loop 3 above, only “1” will be taken, leaving our arrayNumber as {“980”, “760”, “1”} .

Moving on, we will now begin spelling the numbers in arrayNumber by using for loop. To do this, a new int variable j is introduced to store value positionArray from the while loop in line 14. The letter j is used to distinguish it from i that was used previously. We start with the biggest positionArray in a descending order (j- -) to work backwards. This way the first group of three-digits will be spelled first. Let’s show this logic (line 21–29) by continuing the example above:

Suppose one of the stored value of arrayNumber equals 000 (if the input contains “000”), then no extension will be added and the program will only run line 22 and skip to line 32. As none of our arrayNumber value equal “000”, we will move on to line 22.

Line 22 will convert value of into words by using converter function and store the result in String arrayResult. As a result, we will have “1” spelled as “Satu”. You might be wondering how the converter function performs it, or why converter is not part of the main() method. We will get to this in the Sub-Method section later.

From Loop 2, the biggest positionArray is 2. Hence, j : 2

Line 24 j==2 (true) so the extension “Juta” will be printed after “Satu”.

Then the for loop will repeat itself for other values of j. Subsequently, program returns to line 22.

From Loop 1, positionArray is 1. Hence, j : 1 and “Tujuh Ratus Enam Puluh” will be printed after “Juta”.

Line 27 j==1 (true) so the extension “Ribu” will be added behind “Tujuh Ratus Enam Puluh”.

Now for j : 0, only line 23 will be executed as the value does not satisfy the boolean conditions stated in lines 24–28. Thus, “Sembilan Ratus Delapan Puluh” is printed without any extension and the program will break out of the if loop, continuing to line 32.

3) Result

The last step in the main method would be to print the amount stored in String arrayResult on screen using System.out function.

System.out.println(arrayResult);

Sub-Method

Here are the functions that are used in the main() method but are not defined there in order to make the code look more succinct. By defining them separately, we can also call / use these functions in another class. In order to do so the sub-method should be “public” and not “private”. As I am not planning to use these functions elsewhere, I created the converter and numberText methods privately.

1) converter

This function works to return the value of arrayNumber . As we have parsed it into a maximum of three digits, the converter can only recognize ones, tens (puluh), and hundreds (ratus). In order to perform such function, a similar procedure is followed: take the length of the String and add prefixes when necessary. These prefixes should have a separate code on its own as they deviate from the normal conventions.

Several prefixes and exceptions to note:

  • In IDR, the prefix Se- is used to say “100”. The number is spelled “Seratus” and not “Satu Ratus
  • “10” and “11” are spelled “Sepuluh” and “Sebelas” and not “Satu Puluh” nor “Satu Puluh Satu
  • If value of String at i is 0, we only return an an empty space “” without “Ratus” or “Puluh” extensions

I make use of for loops, and if-else conditions to create such exceptions:

converter function

The returned result will now function as an argument each time the converter function is called in the main method or in other classes.

2) numberText

This function complements the converter function above. Its job is to recognize the number and prints its words. Each time numberText(amountString.charAt(i)) is used, the function numberText will return a word that represents the character at i. The function switch-case is used to show the different possible numbers that might show up. Recall to always follow each case with a break so that the loop breaks after the program finishes finding the assigned word.

numberTex function

Bryan’s Version (English)

In this version, Bryan added comments in his code window to keep track of the steps he carried out whilst also making it easier for readers to follow. These comments are printed in grey using this //format.

Essentially his program runs this way: parse the input into ones, tens, hundreds, and so on. From here, the functionsconvertHundreds, convertThousands, and convertTens are used to convert the number accordingly.

  • For Single Digit Numbers: The program simply returns a String from a pre-determined array of all the numbers from zero to nine
  • For Two-Digit Numbers (10 to 19): These too similarly only returns a String from a pre-determined array of the special tens
  • For Two-Digit Numbers (20 and above): Program looks at the first digit and takes a String from an array that contains values such as {Twenty, Thirty, Forty and so on}. So if the first digit is a 6, the String will start with a Sixty.
  • For the Three-Digit Numbers: Program takes the last two digits of the number and runs it through the convertTens method. Afterwards, it takes the first digit of the number and converts it through the same method as the Single-Digit Numbers.
  • Afterwards, it will look at the second digit and repeats the procedure for the Single-Digit Numbers
  • Finally, it concatenate both these strings

However, note that for every single one of these convert methods, there is an exception for numbers which only ends with zeros. As an example, 1000, is set to be one thousand instead of one thousand zero. 1000000, This must also be set to one million instead of one million zero

This seperateDigits function is the way Bryan parses the digits. Here his method is quite different from mine.

  • Last digit of input is placed into an array with help of modulo 10 operator
  • Modulo operator takes the remainder of a division. For example, in modulo 10 operator, the modulo of 456 is 6, hence 6 is placed in the array
  • Since Java truncates numbers instead of rounding it, any decimal digits will be removed. So dividing by 10 will basically remove the last digit (eg. 456 become 45.6 but Java makes it 45)
  • These steps are then repeated until the number is zero and all the digits are placed in the array
  • seperateDigits will then returnnumDigits, which will be converted and processed in the main method
Final Result

Key Takeaway:

  • There are lots of ways to code for the same result, some might be more efficient than others :)

--

--