Problem Solving: Printing Numbers in Words
Let's think up a solution to print the digits of a number in words.
We'll cover the following
In this lesson, we will think of a solution together to write a program that takes a number, and prints the digits of the number in words.
Printing numbers in words
Write a program that will take at most a 3-digit number and output each of its digits in words.
Sample input:
432
Sample output:
Four Three Two
Designing the strategy (algorithm)
We have already seen how to separate each digit from a number in the “Problem Solving: Sum of Digits” lesson.
Using what we learned, we are going to separate each digit from the number and then print it in words and repeat for all digits.
Let’s break it down:
So let’s say the number we want to convert to words is stored in the variable num
. Let’s suppose num
is equal to 651
.
-
In the sum of digits problem, we saw that using
num % 10
, we could separate the last digit. So, let’s say we store the last digit,1
, in thedigit
variable. -
We also saw that by using
num / 10
, we could remove the last digit from the number. So let’s say we save the remaining digits,65
, (after removing the last digit) and update the variablenum
. -
We print the
digit
in words. So,one
is printed.
Since we need to repeat the same for all digits, we perform the above steps inside a while
loop. So, repeating the above steps would print five
, followed by six
.
So we’ll have the following if we simply use the if
conditions:
while(num != 0){div = num % 10;num = num / 10;// since there are 10 possible digitsif(digit == 0)cout << "zero" << endl;if(digit == 1)cout << "one" << endl;// and so on for the rest of the digits...if(digit == 9)cout << "nine" << endl;}
But did you see the problem with the above method? The number 651
prints one five six
, which is the reverse of the number. While this method worked when we wanted to calculate the sum of the digits, it will not work for this problem.
If you’ve understood the problem, that’s great. If you still did not understand, run the code step by step in the code editor below to see what we mean. But if you’ve realized the problem, you may skip running the code below:
#include <iostream> using namespace std; // Printing the digits in words int main() { int num, digit; cout << "Number: " << endl; cin >> num; while(num != 0) { digit = num % 10; num = num / 10; // since there are 10 possible digits if(digit == 0) cout << "zero" << " "; if(digit == 1) cout << "one" << " "; if(digit == 2) cout << "two" << " "; if(digit == 3) cout << "three" << " "; if(digit == 4) cout << "four" << " "; if(digit == 5) cout << "five" << " "; if(digit == 6) cout << "six" << " "; if(digit == 7) cout << "seven" << " "; if(digit == 8) cout << "eight" << " "; if(digit == 9) cout << "nine" << " "; } return 0; }
We will see how to fix this reverse printing. We would encourage you to pause and think about the possible solution yourself before looking at the solution below.
Displaying the words in the right order
Hopefully, now you know that we must do something to print the digits in the right order.
We can do this in two ways:
-
We can first take the reverse of the number and then simply print the digits (we’ll see how at the end of this lesson). We leave this idea as an exercise for you.
-
We can simply tweak our above code, and instead of removing digits from the right, remove the digit from the left one by one and print it.
Observe the following:
Let
int num = 3578;
. If we dividenum
by1000
, what will we get? It will be 3. So, to get3
(the first digit ofnum
), we can divide by1000
. Now, instead of shrinking (removing) from the right, how can we cut from the left? We takenum=num%1000
. Then, what do we do to get the next digit5
? We divide578
with100
, shrink bynum=num%100
, and so on.So instead of using
digit = num % 10
to get the right most digit, we can divide thenum
with1000
,100
, or10
depending on the number of digits in the number to get the first digit.
Let’s write code assuming we only have a 3-digit number. So let’s create a new int
variable called div
and initialize it with 100
(for only 3-digit numbers).
int div = 100;
- Then, to get the first digit, we write:
digit = num / div;
- Then, we store the remaining number in
num
:
num = num % div;
- Lastly, we divide
div
(which is100
) with10
and store the result indiv
.
// So 100 would be updated to 10, and 10 would be updated with 0 in div after each iteration when we place it inside the loop
div = div / 10;
- That’s it. The rest of the code would remain the same, except that we also need to add a condition that ensures the input entered is not more than three digits.
Let’s implement this idea (using if
, if - else
, and switch
statements). We will also improvise to create better versions incrementally.
Implementation 1: The if
statements
Look at the code below and run it to understand how it works:
#include <iostream> using namespace std; // Printing the digits in words int main() { int num, digit, div = 100; cout << "3-digit number: " << endl; // let's say the user entered num = 246 cin >> num; if(num > 999 || num <= 99) cout << "The number should be a three-digit number."; else { while(num != 0) { // digit = 2 (in first iteration) digit = num / div; // num = 46 (in first iteration) num = num % div; // div = 10 (in first iteration) div = div / 10; // since there are 10 possible digits if(digit == 0) cout << "zero" << " "; if(digit == 1) cout << "one" << " "; if(digit == 2) cout << "two" << " "; if(digit == 3) cout << "three" << " "; if(digit == 4) cout << "four" << " "; if(digit == 5) cout << "five" << " "; if(digit == 6) cout << "six" << " "; if(digit == 7) cout << "seven" << " "; if(digit == 8) cout << "eight" << " "; if(digit == 9) cout << "nine" << " "; } } return 0; }
In line 15 in the code above, the while
condition would be true as long as num != 0
. In line 11, the if
condition filters out any number greater than 999
(maximum 3-digit number) and less than or equal to 99
.
Solve the quiz below to check your understanding of the code above.
If the value stored in num
was 489
, how many if
conditions would be checked in the first iteration?
5
10
If you got the answer to the quiz wrong, that means you haven’t really understood the working of the code. Run the code step by step to see how each code executes.
Exercise: What is wrong with Implementation I?
Try executing the above code again on the inputs 900
, 190
, and 170
. Did you find a mistake? How should we fix it?
Instruction: Modify the code in the editor above to fix this issue with printing zeroes in the end. You may look at the hint above to fix this problem.
In the second implementation, we will also add the part about fixing the trailing zeroes of the code.
Implementation 2: The if-else
statements
Now let us modify the code and try if-else
statements instead of if
statements. Let’s run the code below to see the output:
#include <iostream> using namespace std; // Printing the digits in words int main() { int num, digit, div = 100; cout << "3-digit number: " << endl; // let's say the user entered num = 246 cin >> num; if(num > 999 || num <= 99) cout << "The number should be a three digit-number."; else { for(int di=1; di<=3; di++) // while is being replaced with for. { // This will ensure that the last ending // zeroes are being printed too. digit = num / div; // digit = 2 num = num % div; // num = 46 div = div / 10; // div = 10 // since there are 10 possible digits if(digit == 0) cout << "zero" << " "; else if(digit == 1) cout << "one" << " "; else if(digit == 2) cout << "two" << " "; else if(digit == 3) cout << "three" << " "; else if(digit == 4) cout << "four" << " "; else if(digit == 5) cout << "five" << " "; else if(digit == 6) cout << "six" << " "; else if(digit == 7) cout << "seven" << " "; else if(digit == 8) cout << "eight" << " "; else cout << "nine" << " "; } } return 0; }
If the value stored in num
was 489
, how many if-else
conditions would be checked in the first iteration?
1
10
5
4
If you answered the quiz correctly, you would know that the code above that uses if-else
is comparatively more efficient than the previous one. That’s because all the if
conditions are checked in the code with only if
conditions. On the other hand, in the code with only if-else
conditions, as soon as an else if
condition becomes true, the rest of the code is not checked.
Can we further improve the code? Yes! Let’s see how in our third implementation.
Implementation 3: The switch
statements
Now let’s try using the switch
statement instead of the if-else
statement and removing the condition on the number of digits.
Here’s the idea:
-
We will first count the number of digits in a given number by removing each digit from right to left. This way, the numbers with a trail of zeroes, like
19000
, if cut from the left, will become zero with two digits removal, but if cut from the right, will give us the exact number of digits (digitsCount
). -
We will create a
div
and multiply it by10
in each iteration, to get one less digit than the number of digits. This is because shrinking the number789
from the left requires division by100
(for the first digit, division by100
, and for the remaining two digits,%
by100
). -
Repeat the printing procedure now in a
for
loop, the number of digits time, and print usingswitch
statement, with repeated division with shrinking power of10
, like for 4-digit number,div
should shrink like1000
,100
,10
and so on.
Let’s see the code:
#include <iostream> using namespace std; // Printing the digits in words int main() { int num, n, digit, div=1, digitsCount=0; cout << "Enter a number: " << endl; cin >> num; // e.g. 1234 int temp = num; while(temp!=0) { temp=temp/10; // temp will become 123, // then 12 and then 1, and then 0 digitsCount++; } // Now creating div for(int i=1; i<digitsCount; i++) div*=10; for(int i=1; i<=digitsCount; i++) { digit = num / div; num = num % div; div = div / 10; switch(digit) { // since there are 10 possible digits case 0: cout << "zero" << " "; break; case 1: cout << "one" << " "; break; case 2: cout << "two" << " "; break; case 3: cout << "three" << " "; break; case 4: cout << "four" << " "; break; case 5: cout << "five" << " "; break; case 6: cout << "six" << " "; break; case 7: cout << "seven" << " "; break; case 8: cout << "eight" << " "; break; case 9: cout << "nine" << " "; break; default: cout << "Invalid input" << " "; } } return 0; }
Solve the quiz below to check your understanding of the code above.
If the value stored in num
was 489
, how many switch
case labels would be executed in the first iteration?
3
1
10
5
During compilation, a jump table is generated for each switch
by the compiler. So, the switch
statement directly jumps to the case that is equal to the expression (placed in the switch (expression)
) instead of checking which case is satisfied. So the case that is equal to the expression in a switch
statement is executed directly. So, a far better implementation.
We can achieve the same result with the
if-else
andswitch
statements. However, when there are a lot of cases with constant values to be compared, theswitch
statement is mostly preferred.
With these three implementations, we have incrementally learned how to use the if
, if-else
, and switch
statements as control structures inside a repetition loop. We have compared all three to see which strategy can be opted as the best solution.
Below is a challenge for you.
Exercise: Reversing the number and then printing digit by digit
Remember how in the beginning we mentioned that there was another way that we could solve the issue of printing digits in reverse? One of the two ways we mentioned was to first reverse all the digits and store them in num
first as shown below:
int reverse = 0;while (num != 0){digit = num % 10;reverse = (reverse * 10) + (num % 10)num = num / 10;}
We can first take the reverse of the number and store it inside the num
variable using a while
loop. And then simply print the digits.
However, for numbers that include zeroes, for example, 1200
, we would not be able to print the zeroes (only one two
would be printed) using this method. In that case, we’ll need to keep a count of the number of zeroes and print those as well.
Use this method along with the switch
statement to solve the problem in the code editor below:
#include <iostream> using namespace std; // Printing the digits in words int main() { int num, digit; cout << "Number: " << endl; cin >> num; /* Write the code for reverse here. In case of zeroes in the end maintain a count of zeroes that can be used to print zeroes in the end. */ while(num != 0) { digit = num % 10; // getting the last digit num = num / 10; // cutting the right-most digit // since there are 10 possible digits // add a switch for printing digit } /* Write code for printing zeroes */ return 0; }
We hope you enjoyed this problem solving walk-through. We could have come up with the optimized solution at the start but we wanted you to understand why and how different control structure statements work.