0

I have written a code for converting numbers to words considering the constraint 1<=number<=1000000000 (Indian Numbering System).

I have used a HashMap in its implementation.

The problem is I can't get output for some special case numbers. Is there any alternate and efficient way of implementing this.

Code

import java.util.HashMap;
import java.util.Scanner;

public class NumberToString {

    public static void main(String[] args) {
        HashMap<Long, String> hm = new HashMap<Long, String>() {
            {
                put(0L, "Zero");
                put(1L, "One");
                put(2L, "Two");
                put(3L, "Three");
                put(4L, "Four");
                put(5L, "Five");
                put(6L, "Six");
                put(7L, "Seven");
                put(8L, "Eight");
                put(9L, "Nine");
                put(10L, "Ten");
                put(11L, "Eleven");
                put(12L, "Twelve");
                put(13L, "Thirteen");
                put(14L, "Fourteen");
                put(15L, "Fifteen");
                put(16L, "Sixteen");
                put(17L, "Seventeen");
                put(18L, "Eighteen");
                put(19L, "Nineteen");
                put(20L, "Twenty");
                put(30L, "Thirty");
                put(40L, "Fourty");
                put(50L, "Fifty");
                put(60L, "Sixty");
                put(70L, "Seventy");
                put(80L, "Eighty");
                put(90L, "Ninety");
            }
        };

        int multiplier = 1;
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter a number:");
        String numberString = scanner.nextLine();
        try {
            if (Long.parseLong((numberString)) == 0) {
                System.out.println("Enter a number greater than zero");
                System.exit(0);
            }
        } catch (NumberFormatException e) {
            System.out.println(numberString + "is not a number");
            System.exit(0);
        }
        Long[] numberInteger = new Long[numberString.length()];
        for (int i = 0; i < numberInteger.length; i++) {
            numberInteger[i] = (long) (numberString.charAt(i) - '0');
        }

        for (int i = (numberInteger.length - 1); i >= 0; i--) {
            numberInteger[i] = numberInteger[i] * multiplier;
            multiplier = multiplier * 10;
        }
        int temp = 0;
        for (int i = 0; i < numberInteger.length; i++) {
            int counter = 0;
            while (numberInteger[i] != 0 && numberInteger[i] % 10 == 0) {
                counter++;
                numberInteger[i] = numberInteger[i] / 10;
            }
            if (counter == 9)
                System.out.print(hm.get(numberInteger[i]) + " hundred and ");
            else if (counter == 8) {
                if ((Long.parseLong(numberString)) % 10 == 0)
                    System.out.print(hm.get(numberInteger[i] * 10) + " crores ");
                else
                    System.out.print(hm.get(numberInteger[i] * 10) + " ");
            } else if (counter == 7)
                System.out.print(hm.get(numberInteger[i]) + " crores ");
            else if (counter == 6) {
                if ((Long.parseLong(numberString)) % 10 == 0)
                    System.out.print(hm.get(numberInteger[i] * 10) + " lakhs ");
                else
                    System.out.print(hm.get(numberInteger[i] * 10) + " ");
            } else if (counter == 5)
                System.out.print(hm.get(numberInteger[i]) + " lakhs ");
            else if (counter == 4) {
                if ((Long.parseLong(numberString)) % 10 == 0)
                    System.out.print(hm.get(numberInteger[i] * 10) + " thousand");
                else
                    System.out.print(hm.get(numberInteger[i] * 10) + " ");
            } else if (counter == 3)
                System.out.print(hm.get(numberInteger[i]) + " thousand ");
            else if (counter == 2)
                System.out.print(hm.get(numberInteger[i]) + " hundred ");
            else if (counter == 1) {
                if (numberInteger[i] == 1) {
                    temp = 10;
                    continue;
                } else
                    System.out.print(hm.get(numberInteger[i] * 10) + " ");
            } else if (counter == 0) {
                if (temp == 10)
                    System.out.print(hm.get(numberInteger[i] + temp));
                if (numberInteger[i] > 0 && temp != 10)
                    System.out.print(hm.get(numberInteger[i]));
            } else
                System.out.print(hm.get(numberInteger[i]));
        }
        scanner.close();
    }
}
5
  • Please be more specific: what does not work? Any examples? Commented Nov 16, 2016 at 10:24
  • Possible duplicate of How to convert number to words in java Commented Nov 16, 2016 at 10:30
  • "I can't get output for some special case numbers" - so you should include those in your question and clearly say what are expected and actual values. Otherwise, you are just asking for code review and Stack Overflow is not a place for this. Commented Nov 16, 2016 at 10:32
  • For these numbers, 1000001,1000000001, it will give improper outputs. Commented Nov 16, 2016 at 10:33
  • @abubakkar Take a look at my answer. Commented Nov 16, 2016 at 13:22

1 Answer 1

2

As shown here, there is no method in Java that does this for you.

What you could do is try to create a method that generates the string for the number.

So this method would have all the strings required to represent every number:

zero - nine, ten, twenty, thirty , hundred, thousand, [m-b-tr-quad..]illion 
eleven, twelve, thirteen and negative

14 - 19 => [4-9] + teen
30 - 90 => [3-9] + ty
10^6 - 10^3n => [m for 10^6, b for 10^9] + illion

You would have to remove the overlapping ts .

i.e. It's Eighty and not Eightty.

I just created a program that works for -1000000000 < n < 1000000000. Sorry for the delay but I wanted to make sure that it worked properly.

Code

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NumberConversion {
    public static final int MAX_NUMBER = 999999999;// up to almost 1 billion
    public static final HashMap<Integer, String> numbers;
    public static final HashMap<String, String> patterns;
    public static final String NEGATIVE = "Minus ";
    public static final String ZERO = "Zero";

    static {
        numbers = new HashMap<Integer, String>();
        numbers.put(0, "");
        numbers.put(1, "One");
        numbers.put(2, "Two");
        numbers.put(3, "Three");
        numbers.put(4, "Four");
        numbers.put(5, "Five");
        numbers.put(6, "Six");
        numbers.put(7, "Seven");
        numbers.put(8, "Eight");
        numbers.put(9, "Nine");
        numbers.put(10, "Ten");
        numbers.put(11, "Eleven");
        numbers.put(12, "Twelve");
        numbers.put(13, "Thirteen");
        numbers.put(15, "Fifteen");
        patterns = new HashMap<String, String>();
        patterns.put("1[4-9]", "[]teen ");
        patterns.put("2.", "Twenty ");
        patterns.put("3.", "Thirty ");
        patterns.put("[4-9].", "[]ty ");
        patterns.put("[1-9]..", "[] Hundred ");
        patterns.put("[0-9]{1,3}...", "[] Thousand ");
        patterns.put("[0-9]{1,3}......", "[] Million ");
    }

    public static String getValue(int number) {
        return number != 0 ? getValue(String.valueOf(number)) : "Zero";
    }

    public static String getValue(String number) {
        // Validation
        int parsed = Integer.parseInt(number);
        if (parsed > MAX_NUMBER) {
            throw new IllegalArgumentException("The number: '" + number + "' is too large to be converted.");
        }
        if (parsed < 0) {
            return NEGATIVE + getValue(number.substring(1));
        }
        // If the number exists in the numbers map, return it as is.
        if (numbers.containsKey(parsed)) {
            return numbers.get(parsed);
        }
        StringBuilder result = new StringBuilder();// The returned string
        Iterator<Entry<String, String>> iterator = patterns.entrySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next().getKey();
            Pattern pattern = Pattern.compile(key);
            Matcher matcher = pattern.matcher(number);
            if (matcher.matches()) {
                int index = key.indexOf('.');
                String temp;
                if (index <= 0) {
                    index = key.indexOf('[');
                    temp = number.substring(index);
                } else {
                    int size = key.length() - index;
                    index = number.length() - size;
                    temp = number.substring(0, index);
                }
                String string = patterns.get(key);
                number = number.substring(index);
                result.append(string.replace("[]", getValue(temp)));
            }
        }
        if (number != "") {
            /*
             * In the event of having a number like 121. The output will be 120
             * and the variable number will still hold the 1.
             */
            result.append(getValue(number));
        }
        // Eightten -> Eighteen, Eightty -> Eighty
        return result.toString().replace("tt", "t");
    }

    public static void main(String[] args) {
        System.out.println(getValue(312321));
    }
}

If you want to add patterns.put("[0-9]{1,3}.........", "[] Billion "); You will have to change every int to long.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.