2
\$\begingroup\$

I'm relatively new to Java, and over the past week or so I've just been reading through the docs and messing around with it to better improve my understanding.

As stated in the title, I've created a method to convert numbers (between 0 - 999,999,999) into plain text, and I would love some feedback/constructive criticism regarding ways that I could improve.

Code in question: https://ideone.com/jNf7ZR

There are obvious limitations currently, in that it only supports up to 3 digits, an natural numbers, but those wouldn't be too hard to implement - I just haven't yet.

        private static final String[]   NUM_NAMES   = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

private static final String[]   TEEN_NAMES  = { "", "eleven", "twelve", "thirteen", "fourteen",
        "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };

private static final String[]   TENS_NAMES  = { "", "ten", "twenty", "thirty", "forty", "fifty",
        "sixty", "seventy", "eighty", "ninety" };

private static int getRemainder(int dividend, int i, int k) {
    return ((dividend % (int) Math.pow(10, (i))) - (dividend % (int) Math.pow(10, (k))))
            / (int) Math.pow(10, (k));
}

/*
 * The method convertNumToText is capable of evaluating numbers up to 999,999,999 and
 * translating them into their readable English equivalent.
 */
private static String convertNumToText(int num) {
    // Uses StringBuilder to append values instead of String concatenation
    StringBuilder str = new StringBuilder();
    // Calculates the logarithmic value for the number entered
    int length = (int) (Math.log10(num));
    // Placeholder variable for the result of modulus calculations
    int remainder;

    // Catches if the number being parsed is 0 and returns "zero"
    if (num == 0) {
        return "zero";
    }

    /*
     * This For Loop isolates every digit of the number entered,
     * and appends the English value into a string
     */
    for (int i = length; i >= 0; i--) {

        /*
         * Isolates the highest-level digit using modulus
         * e.g. : ((4321%10^4) - (4321%10^3) / 10^3)
         * = ((4000) - (321)) / 1000
         * = 4
         */
        remainder = getRemainder(num, i + 1, i);

        /*
         * IF the digits place is tens AND the value is not 10 (11-19) then apply the nomenclature of
         * TEEN_NAMES
         * 
         * ELSE if the digits place is tens and 10,20,30... then apply the nomenclature TEN_NAMES
         * 
         * ELSE if no special nomenclature is required, just apply regular nomenclature NUM_NAMES
         */
        if ((i == 1 || i == 4 || i == 7) && (remainder == 1 && ((10 + getRemainder(num, i, i - 1) != 10)))) {
            str.append(TEEN_NAMES[getRemainder(num, i, i - 1)]);
            i--; // Skip the ones value, since the TEENS naming consumes both tens and ones
        } else if (i == 1 || i == 4 || i == 7) {
            str.append(TENS_NAMES[remainder]);
            if (getRemainder(num, i, i - 1) != 0 && getRemainder(num, i+1, i) != 0) {
                str.append("-"); // If the value of the ones is not zero, then append a dash
            }
        } else {
            str.append(NUM_NAMES[remainder]);
        }

        /*
         * If the digit places is hundreds, then apply suffix of "hundred"
         * 
         * This is not a part of the thousand/million statements because those only have one
         * placeholder and hundred has multiple
         */
        if (remainder > 0 && (i == 2 || i == 5 || i == 8)) {
            str.append(" hundred ");
        }

        /*
         * IF the digits place is thousands, then apply suffix "thousand"
         * 
         * ELSE IF the digits place is millions, then apply suffix "million"
         * 
         * New line added for readability.
         */
        if (i == 3) {
            str.append(" thousand,\n");
        } else if (i == 6) {
            str.append(" million,\n");
        }
        // For debugging purposes
        //System.out.println(remainder + " " + i);
    }
    // Converts the StringBuilder str into a string and returns the value
    return str.toString();
}
public static void main (String[] args) throws java.lang.Exception
{

System.out.println(convertNumToText(231242));
}
\$\endgroup\$
2
\$\begingroup\$

Some comments:

  • There's no need for this fancy getRemainder business. To get the digits starting at the lowest, repeatedly add your number % 10 to a list of digits and then divide your number by 10 until the number is 0. Then reverse the digits to put them in order from largest to smallest place and operate on that list.

  • Don't have two top-level if clauses checking i == 1 || i == 4 || i == 7. Put this condition in one if clause containing an if/else on the remaining condition.

  • i == 1 || i == 4 || i == 7 and i == 2 || i == 5 || i == 8 can more succinctly be expressed as (i % 3) == 1 and (i % 3) == 2.

  • Declare the remainder variable in the loop. Generally, declare variables with as narrow scope as possible to minimize accidental misuse. Some think declaring variables out of the loop aids performance but in reality it probably doesn't and until you measure a difference, don't assume anything.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy