HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

Converting a number to the text representation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
numberthetextconvertingrepresentation

Problem

Following along with some previous questions:

  • The @dbasnett original here: Number to Words



  • @nhgrif's here: Int extension for translating integer to plain English



I wanted to answer the original question with a different algorithm, but was not able to get the VB.net code to work. I see @nhgrif had the same idea as me, and proposed a Swift solution.

This is the algorithm I would use, but in Java.

Like other questions, I am looking for possible improvements, or suggestions for other aspects that may make this more robust, and more usable.

```
public class IntToText {

private static final String[] SCALES = {"", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion"};
private static final String[] SUBTWENTY = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
private static final String[] DECADES = {"zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

/**
* Convert any value from 0 to 999 inclusive, to a string.
* @param value The value to convert.
* @param and whether to use the word 'and' in the output.
* @return a String representation of the value.
*/
private static final String tripleAsText(int value, boolean and) {
if (value = 1000) {
throw new IllegalArgumentException("Illegal triple-value " + value);
}

if (value 0) {
sb.append(SUBTWENTY[hun]).append(" hundred");
}
if (subhun > 0) {
if (hun > 0) {
sb.append(and ? " and " : " ");
}
if (subhun 0) {
sb.append(DECADES[tens]);
}
if (units > 0) {
sb.append(" ").append(SUBTWENTY[units]);
}
}

Solution

I would define DECADES[0] as "" instead of "zero" so that the if (tens>0) can be removed. Notice that DECADES[0] was never used and its value "zero" was a repetition with respect to SUBTWENTY[0].

Also there is a repetition in the creation of the "subhundred" part of the number.

In fact you can safely remove this part of code:

if (value < SUBTWENTY.length) {
        return SUBTWENTY[value];
    }


which is anyway correctly handled by the code following.

Looking carefully you see that there is a problem with the handling of "zero". Try your code with 1000 to see that it doesn't work.

Notice however that the tripleAsText should return the emptystring when value is 0, because "zero" should be considered as a special case and trapped in the main function (notice that "zero" is never used in the spelling of numbers apart from zero itself).

So your function could be simplified as:

private static final String[] SCALES = {"", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion"};
private static final String[] SUBTWENTY = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
                                           "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
private static final String[] DECADES = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

/**
 * Convert any value from 0 to 999 inclusive, to a string.
 * @param value The value to convert.
 * @param and whether to use the word 'and' in the output.
 * @return a String representation of the value.
 */
private static final String tripleAsText(int value, boolean and) {
    int subhun = value % 100;
    int hun = value / 100;
    StringBuilder sb = new StringBuilder(50);
    if (hun > 0) {
        sb.append(SUBTWENTY[hun]).append(" hundred ");
        if (subhun > 0 && and) {
            sb.append("and ");
        }
    }
    if (subhun 0) {
          sb.append(" ");
        }
        sb.append(SUBTWENTY[units]);
    }

    return sb.toString();
}

Code Snippets

if (value < SUBTWENTY.length) {
        return SUBTWENTY[value];
    }
private static final String[] SCALES = {"", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion"};
private static final String[] SUBTWENTY = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
                                           "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
private static final String[] DECADES = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

/**
 * Convert any value from 0 to 999 inclusive, to a string.
 * @param value The value to convert.
 * @param and whether to use the word 'and' in the output.
 * @return a String representation of the value.
 */
private static final String tripleAsText(int value, boolean and) {
    int subhun = value % 100;
    int hun = value / 100;
    StringBuilder sb = new StringBuilder(50);
    if (hun > 0) {
        sb.append(SUBTWENTY[hun]).append(" hundred ");
        if (subhun > 0 && and) {
            sb.append("and ");
        }
    }
    if (subhun < SUBTWENTY.length) {
        sb.append(SUBTWENTY[subhun]);
    } else {
        int tens = subhun / 10;
        int units = subhun % 10;
        sb.append(DECADES[tens]);
        if (units>0) {
          sb.append(" ");
        }
        sb.append(SUBTWENTY[units]);
    }

    return sb.toString();
}

Context

StackExchange Code Review Q#58884, answer score: 11

Revisions (0)

No revisions yet.