need help converting numbers to word in Java

2019-02-27 23:41发布

I'm working on a program that converts numbers to words, but I'm having problems with the toString() method in the Numbers class. All the methods were given to me, so I could implement; therefore, I can't remove any of them...

number: 4564 --> four thousand and five hundred and sixty four

here's the code Numbers class

package numberstowords;

import java.util.*;

public class Numbers {

    //array containing single digits words numbers:0-9
    private final String[] SINGLE_DIGITS_WORDS;

    //array containing special words words eg:10-19
    private final String[] TEEN_DIGITS_WORDS;

    //array containing tens words numbers:20-90
    private final String[] TEN_DIGITS_WORDS;

    private int value,   //number to be converted to words
                one,     //number to store digits
                ten,     //number to store tens
                hundred, //number to store hundred
                thousand;//number to store thousand

    private String strOut;

    //conscructor: Initializing value and arrays
    public Numbers(int n)


    //getting single digit number
    private int getOnes()
    {
        one = value % 10;
        return one;
    }

    //getting tens numbers
    private int getTens()
    {
        ten = value % 100;
        ten /= 10;
        return ten;
    }

    //getting hundreds numbers
    private int getHundreds()
    {
        hundred = value % 1000;
        hundred /= 100;
        return hundred;
    }

    //getting thousands numbers
    private int getThousands()
    {
        thousand = value % 10000;
        thousand /= 1000;
        return thousand;
    }

    //converting and returning string of ones 
    private String digitsToString(int one)
    {
        return SINGLE_DIGITS_WORDS[one];        
    }

    //converting and returning strings of tens and teens
    private String tensAndOnesToString(int ten, int one)
    {
        if(ten == 1)//if number is a teen return, else return tens 
        { 
            return TEEN_DIGITS_WORDS[one];
        }
        return TEN_DIGITS_WORDS[ten-2];         
    }

    //converting and returning strings of hundreds
    private String hundredsToString(int hundred)
    {
        return digitsToString(hundred) + " hundred";
    }

    private String thousandsToString(int thousand)
    {
        return digitsToString(thousand) + " thousand";
    }

2条回答
ゆ 、 Hurt°
2楼-- · 2019-02-27 23:46

In this short code, I'd used recursive functions to make it simple answer with good performance. I divide the given number to small pieces of math understandable values. This type of divide is math based, which do mostly by the CPU and use smaller amount of memory.

public class NumbersLetter {

    private java.util.HashMap<Long, String> hashMap = new java.util.HashMap<>(34);
    private long[] dividers = {
            1_000_000_000_000_000_000L, 1_000_000_000_000_000L, 1_000_000_000_000L,
            1_000_000_000L, 1_000_000L, 1_000L, 100L, 10L, 1L};

    public String getNaturalNumbersLetter(long number) {
        String regex = "[0-9]+";
        if (!Long.toString(number).matches(regex)) {
            number = 0;
        }
        return divideNumber(number);
    }

    private String getDigitLetter(long digit) {
        return hashMap.get(digit);
    }

    private String addSeparation(boolean addSeperator) {
        if (addSeperator) return " and ";
        return "";
    }

    private String divideNumber(long digit) {
        //Check if the number is a pure number
        // and mapped in our @hashMap
        if (hashMap.containsKey(digit)) {
            return " " + getDigitLetter(digit);
        }
        // Start to divide the given number
        // to small pieces of math understandable values
        // This type of divide is math based
        // which do mostly by the CPU and
        // use small amount of RAM.
        for (long i : dividers) {
            /**
             * Start divide the given number to smaller pieces
             * for example will change 4,321 to
             * 4000 , 300 ,20 & 1
             * this is one of those formats which is human readable.
             * The important thing about this design is that
             * I use calculation instead of buffering strings.
             * */
            if ((digit >= i)) {
                if (digit % i == 0) {
                    //
                    return divideNumber(digit / i) + divideNumber(i);
                } else {
                    if ((digit / i) == 1) {
                        return divideNumber(digit / i)
                                + divideNumber((digit / i) * i)
                                + divideNumber(digit % i);
                    } else {
                        return divideNumber((digit / i) * i)
                                + divideNumber(digit % i);
                    }
                }
            }
        }
        return "";
    }

    public NumbersLetter() {
        // NumbersLetter Constructor
        hashMap.put(0L, "Zero");
        hashMap.put(1L, "One");
        hashMap.put(2L, "Two");
        hashMap.put(3L, "Three");
        hashMap.put(4L, "Four");
        hashMap.put(5L, "Five");
        hashMap.put(6L, "Six");
        hashMap.put(7L, "Seven");
        hashMap.put(8L, "Eight");
        hashMap.put(9L, "Nine");
        hashMap.put(10L, "Ten");
        hashMap.put(11L, "Eleven");
        hashMap.put(12L, "Twelve");
        hashMap.put(13L, "Thirteen");
        hashMap.put(14L, "Fourteen");
        hashMap.put(15L, "Fifteen");
        hashMap.put(16L, "Sixteen");
        hashMap.put(17L, "Seventeen");
        hashMap.put(18L, "Eighteen");
        hashMap.put(19L, "Nineteen");
        hashMap.put(20L, "Twenty");
        hashMap.put(30L, "Thirty");
        hashMap.put(40L, "Forty");
        hashMap.put(50L, "Fifty");
        hashMap.put(60L, "Sixty");
        hashMap.put(70L, "Seventy");
        hashMap.put(80L, "Eighty");
        hashMap.put(90L, "Ninety");
        hashMap.put(100L, "Hundred");
        hashMap.put(1_000L, "Thousand");
        hashMap.put(1_000_000L, "Million");
        hashMap.put(1_000_000_000L, "Billion");
        hashMap.put(1_000_000_000_000L, "Trillion");
        hashMap.put(1_000_000_000_000_000L, "Quadrillion");
        hashMap.put(1_000_000_000_000_000_000L, "Quintillion");
    }

}
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-02-27 23:54

According to your comments, the problem is that you're getting the ones output for numbers between 11-19.

Looking at your tensAndOnesToString() method, it checks whether ten == 1, for the purpose of identifying the teens numbers. So, why don't you put a similar check in your if(d4 != 0) line,

    if(d4 != 0 && d3 != 1) // CHANGED THIS LINE
    {
        if(strOut.equals(""))
            strOut = digitsToString(one);
        else
        {
            strOut = strOut +" "+ digitsToString(one);
        }
    }

So now it will only output a one number if it (d4) isn't 0, and if the tens (d3) isn't 1.

查看更多
登录 后发表回答