Home > Articles > Programming > Java

  • Print
  • + Share This
This chapter is from the book

Convert a Number to Text

This class takes a number and converts it to the equivalent text in English.

For example, the input 1 should return the string "one" and 123,456 should return the string "one hundred twenty three thousand four hundred fifty six." (The program does not try to insert the word "and" between any of the numbers.)

The class has one constructor, which takes the integer to convert as a parameter, and has a single method—getString()—that returns the string. This is not necessarily the ideal interface for such a class, but it works for these purposes.

The constructor uses the pow() method from the Math package, which raises a number to a power. It also uses the substring() method of the String class, which when called with one parameter, creates a new String starting at the specified offset in the original string. (The offset is zero-based.)

Source Code

1.  class EnglishNumber {
2.
3.      private static final String[] ones = {
4.          " one", " two", " three", " four", " five",
5.          " six", " seven", " eight", " nine", " ten",
6.          " eleven", " twelve", " thirteen", " fourteen",
7.          " fifteen", " sixteen", " seventeen",
8.          " eighteen", " nineteen"
9.      };
10.     private static final String[] tens = {
11.         " twenty", " thirty", " forty", " fifty",
12.         " sixty", " seventy", " eighty", " ninety"
13.     };
14.     //
15.    // so quintillions is as big as it gets. The
16.     // program would automatically handle larger
17.     // numbers if this array were extended.
18.     //
19.     private static final String[] groups = {
20.         "",
21.         " thousand",
22.         " million",
23.         " billion",
24.         " trillion",
25.         " quadrillion",
26.         " quintillion"
27.     };
28.
29.     private String string = new String();
30.
31.     public String getString() { return string; }
32.
33.     public EnglishNumber ( long n ) {
34.
35.         // Go through the number one group at a time.
36.
37.         for (int i = groups.length-1; i >= 0; i--) {
38.
39.             // Is the number as big as this group?
40.
41.             long cutoff =
42.                 (long)Math.pow((double)10,
43.                                (double)(i*3));
44.
45.             if ( n >= cutoff ) {
46.
47.                 int thisPart = (int)(n / cutoff);
48.
49.                 // Use the ones[] array for both the
50.                 // hundreds and the ones digit. Note
51.                 // that tens[] starts at "twenty".
52
53.                 if (thisPart >= 100) {
54.                     string +=
55.                       ones[thisPart/100] +
56.                         " hundred";
57.                     thisPart = thisPart % 100;
58.                 }
59.                 if (thisPart >= 20) {
60.                     string += tens[(thisPart/10)-1];
61.                     thisPart = thisPart % 10;
62.                 }
63.                 if (thisPart >= 1) {
64.                     string += ones[thisPart];
65.                 }
66.
67.                 string += groups[i];
68.
69.                 n = n % cutoff;
70.
71.             }
72.         }
73.
74.         if (string.length() == 0) {
75.             string = "zero";
76.         } else {
77.             // remove initial space
78.             string = string.substring(1);
79.         }
80.     }
81. }

Suggestions

  1. Look at the main for loop, running from lines 38–73. What is the goal of one iteration of this loop?

  2. What is the meaning of the variable thisPart?

  3. The functionality is split because the return string is computed in the constructor, but not returned until getString() is called. What variable is returned? Where is it modified?

  4. What is the trivial input for this program? How is it handled in the code?

Hints

Walk through the constructor with the following inputs to the constructor, and determine what value getString() would return:

  1. The trivial case: n == 0.

  2. Test one iteration of the loop, including one case where a digit is 0: n == 102.

  3. Test several iterations of the loop: n == 1234567.

Explanation of the Bug

The code indexes into the ones and tens array incorrectly. Because arrays are zero-based, the number 1 corresponds to ones[0], not ones[1]. Thus, the various accesses need to be adjusted for this. Lines 55–57 should change from

string +=
  _ones[thisPart/100] +
    __" hundred";

to

    string +=
      ones[(thisPart/100)-1] +
        " hundred";

Line 61 should change from

    string += tens[(thisPart/10)-1];

to

    string += tens[(thisPart/10)-2];

Line 65 should change from

    string += ones[thisPart];

to

    string += ones[thisPart-1];

This is an A.off-by-one error that becomes a D.index error. It can actually lead to an ArrayIndexOutOfBoundsException being thrown in certain cases. (Can you determine which ones?)

  • + Share This
  • 🔖 Save To Your Account