patternjavaModerate
Converting a number to the text representation
Viewed 0 times
numberthetextconvertingrepresentation
Problem
Following along with some previous questions:
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]);
}
}
- 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
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:
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
So your function could be simplified as:
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.