Java中使用映射继续将整数转换为单词的问题

时间:2018-12-19 23:05:06

标签: java dictionary if-statement macros switch-statement

这可能是我在堆栈溢出中的问题的答案。Integer to word conversion

首先,我从字典开始。然后我才知道它已经过时了。所以现在我用Map代替字典。我的代码可以很好地处理数百万个数字。但是我在这里采取的方法是幼稚的方法。该代码的主要问题是

首先:大量使用变量

2nd:根据程序要求的冗余代码块

第3条:if else语句多个

我正在考虑这个问题

第二个问题的解决方案:使用用户定义函数或宏来消除冗余代码块

第三个问题的解决方案:使用开关盒

我的代码:

public class IntegerEnglish {
public static void main(String args[]){
    Scanner in=new Scanner(System.in);
    System.out.println("Enter the integer");
    int input_number=in.nextInt();
    Map<Integer,String> numbers_converter = new HashMap<Integer,String>();
    Map<Integer,String> number_place = new HashMap<Integer,String>();
    Map<Integer,String> number_2nd = new HashMap<Integer,String>();
    numbers_converter.put(0,"Zero");
    numbers_converter.put(1,"One");
    numbers_converter.put(2,"Two");
    numbers_converter.put(3,"Three");
    numbers_converter.put(4,"Four");
    numbers_converter.put(5,"Five");
    numbers_converter.put(6,"Six");
    numbers_converter.put(7,"Seven");
    numbers_converter.put(8,"Eight");
    numbers_converter.put(9,"Nine");
    numbers_converter.put(10,"Ten");
    numbers_converter.put(11,"Eleven");
    numbers_converter.put(12,"Twelve");
    numbers_converter.put(13,"Thirteen");
    numbers_converter.put(14,"Fourteen ");
    numbers_converter.put(15,"Fifteen");
    numbers_converter.put(16,"Sixteen");
    numbers_converter.put(17,"Seventeen");
    numbers_converter.put(18,"Eighteen");
    numbers_converter.put(19,"Nineteen");
    number_place.put(3,"Hundred");
    number_place.put(4,"Thousand");
    number_place.put(7,"Million");
    number_place.put(11,"Billion");
    number_2nd.put(2,"Twenty");
    number_2nd.put(3,"Thirty");
    number_2nd.put(4,"Forty");
    number_2nd.put(5,"Fifty");
    number_2nd.put(6,"Sixty");
    number_2nd.put(7,"Seventy");
    number_2nd.put(8,"Eighty");
    number_2nd.put(9,"Ninty");

   if(input_number== 0){
       System.out.println("zero");
   }
   else if(input_number>0 && input_number<19){
       System.out.println(numbers_converter.get(input_number));
   }
   else if(input_number>19 && input_number<100){
       int rem=input_number%10;
       input_number=input_number/10;
       System.out.print(number_2nd.get(input_number));
       System.out.print(numbers_converter.get(rem));
   }
   else if(input_number==100){
       System.out.println(number_place.get(3));
   }
   else if(input_number>100 && input_number<1000){
       int reminder=input_number%100;
       int r1=reminder%10;
       int q1=reminder/10;
       int quot=input_number/100;
       System.out.print(numbers_converter.get(quot) + "hundred");
       if(reminder>0 && reminder<20){
           System.out.print(numbers_converter.get(reminder));
       }
       else{
           System.out.println(number_2nd.get(q1) + numbers_converter.get(r1));
       }
   }
   else if(input_number==1000){
       System.out.println(number_place.get(4));
   }
   else if(input_number>1000 && input_number<10000){
       int rem=input_number%100;
       int rem_two=rem%10;
       int quotient =rem/10;
       input_number=input_number/100;
       int thousand=input_number/10;
       int hundred = input_number%10;
       System.out.print(numbers_converter.get(thousand) + "thousand" + numbers_converter.get(hundred)+ " hundred");
       if(rem >0 && rem<20){
           System.out.print(numbers_converter.get(rem));
       }
       else if(rem >19 && rem <100){
           System.out.print(number_2nd.get(quotient) + numbers_converter.get(rem_two));
       }
   }
   else if(input_number>10000 && input_number<1000000000){
       //Say number 418,229,356
       int third_part=input_number%1000;//hold 356
       input_number=input_number/1000;//hold 418,229
       int sec_part=input_number%1000;//hold 229
       input_number=input_number/1000;// hold 418
       int rem_m=third_part%100;//hold 56
       int rem_m1=rem_m%10;//hold 6
       int rem_q=rem_m/10;// hold 5
       int q_m=third_part/100;// hold 3
       int sec_part_rem=sec_part%100;// hold 29
       int sec_part_rem1=sec_part_rem%10;//9
       int sec_part_q=sec_part_rem/10;//hold 2
       int sec_q=sec_part/100;// hold 2
       int input_q=input_number/100;// hold 4
       int input_rem=input_number%100;//hold 18
       int input_q_q=input_rem/10;//hold 1
       int input_rem1=input_rem%10;// hold 8
       System.out.print(numbers_converter.get(input_q) + " hundred ");
       if(input_rem>0 && input_rem<20){
           System.out.print(numbers_converter.get(input_rem)+ " Million ");
       }
       else{
           System.out.print(number_2nd.get(input_q_q) + " " + numbers_converter.get(input_rem1) + " Million ");
       }
       System.out.print(numbers_converter.get(sec_q) + " hundred ");
       if(sec_part_rem >0 && sec_part_rem<20){
           System.out.println(numbers_converter.get(sec_part_rem) + " thousand ");
       }
       else{
           System.out.print(number_2nd.get(sec_part_q) + " " + numbers_converter.get(sec_part_rem1) + " thousand ");
       }
       System.out.print(numbers_converter.get(q_m) + " hundred ");
       if(rem_m>0 && rem_m<20){
           System.out.print(numbers_converter.get(rem_m));
       }
       else{
           System.out.print(number_2nd.get(rem_q) + " " + numbers_converter.get(rem_m1));
       }
   }
  }
   }

冗余代码块

       int rem=input_number%100;
       int rem_two=rem%10;
       int quotient =rem/10;
       input_number=input_number/100;
       int thousand=input_number/10;
       int hundred = input_number%10;

这种代码块几乎在所有地方都使用过。将数字除以100或1000,以找出百位,然后将其除以10,以找出数字的第十位。最后使用%(模数除法)找出一个位置。

我如何包括用户定义功能和切换大小写以最小化代码块。

2 个答案:

答案 0 :(得分:1)

使用方法调用代替将结果存储在变量中:

int remainder100(int aNumber) {
    return aNumber % 100;
}

int remainder10(int aNumber) {
    return aNumber % 10;
}

...etc.

System.out.println(numbers_converter.get(remainder100(input_number)));

关于第三个问题:我不会使用switch ...情况,太多情况。

相反,请利用编号每3位重复一次的优势。这意味着成千上万的模式是相同的(以及数十亿,万亿等)。

为此,请使用如下循环:

ArrayList<String> partialResult = new ArrayList<String>();
int powersOf1000 = 0;
for (int kiloCounter = input_number; kiloCounter > 0; kiloCounter /= 1000) {
    partialResult.add(getThousandsMilionsBillionsEtc(powersOf1000++);
    partialResult.add(convertThreeDigits(kiloCounter % 1000));
}

然后您可以按相反的顺序打印出partialResult的内容,以获得最终编号。

答案 1 :(得分:1)

我建议您将单个main方法分解为几个类。而且,如果您还没有创建一些单元测试来让您轻松地测试/重构。您会发现它比启动应用程序并从stdin中读取内容更快。

您会发现将数字作为字符串更容易处理。您不必一直将其除以10,而只是获取字符串的最后一个字符。您可能有一个可以帮您解决这一问题的类,另一个可以进行转换的类。

这是我想出的,但是我敢肯定它可以改进。它具有PoppableNumber类,该类允许轻松检索初始数字的最后一个字符。还有NumberToString类,它具有静态的convert方法来执行转换。

一个测试示例是

@Test
public void Convert102356Test() {
    assertEquals("one hundred and two thousand three hundred and fifty six", NumberToString.convert(102356));
}

这是NumberToString类:

import java.util.HashMap;
import java.util.Map;

public class NumberToString {

    // billion is enough for an int, obviously need more for long
    private static String[] power3 = new String[] {"", "thousand", "million", "billion"};

    private static Map<String,String> numbers_below_twenty = new HashMap<String,String>();
    private static Map<String,String> number_tens = new HashMap<String,String>();

    static {
        numbers_below_twenty.put("0","");
        numbers_below_twenty.put("1","one");
        numbers_below_twenty.put("2","two");
        numbers_below_twenty.put("3","three");
        numbers_below_twenty.put("4","four");
        numbers_below_twenty.put("5","five");
        numbers_below_twenty.put("6","six");
        numbers_below_twenty.put("7","seven");
        numbers_below_twenty.put("8","eight");
        numbers_below_twenty.put("9","nine");
        numbers_below_twenty.put("10","ten");
        numbers_below_twenty.put("11","eleven");
        numbers_below_twenty.put("12","twelve");
        numbers_below_twenty.put("13","thirteen");
        numbers_below_twenty.put("14","fourteen ");
        numbers_below_twenty.put("15","fifteen");
        numbers_below_twenty.put("16","sixteen");
        numbers_below_twenty.put("17","seventeen");
        numbers_below_twenty.put("18","eighteen");
        numbers_below_twenty.put("19","nineteen");

        number_tens.put(null,"");
        number_tens.put("","");
        number_tens.put("0","");
        number_tens.put("2","twenty");
        number_tens.put("3","thirty");
        number_tens.put("4","forty");
        number_tens.put("5","fifty");
        number_tens.put("6","sixty");
        number_tens.put("7","seventy");
        number_tens.put("8","eighty");
        number_tens.put("9","ninty");
    }

    public static String convert(int value) {
        if (value == 0) {
            return "zero";
        }
        PoppableNumber number = new PoppableNumber(value);

        String result = "";
        int power3Count = 0;
        while (number.hasMore()) {
            String nextPart = convertUnitTenHundred(number.pop(), number.pop(), number.pop());
            nextPart = join(nextPart, " ", power3[power3Count++], true);
            result = join(nextPart, " ", result);
        }

        if (number.isNegative()) {
            result = join("minus", " ", result);
        }

        return result;
    }

    public static String convertUnitTenHundred(String units, String tens, String hundreds) {
        String tens_and_units_part = "";
        if (numbers_below_twenty.containsKey(tens+units)) {
            tens_and_units_part =  numbers_below_twenty.get(tens+units);
        }
        else {
            tens_and_units_part = join(number_tens.get(tens), " ", numbers_below_twenty.get(units));
        }
        String hundred_part = join(numbers_below_twenty.get(hundreds), " ", "hundred", true);
        return join(hundred_part, " and ", tens_and_units_part);
    }

    public static String join(String part1, String sep, String part2) {
        return join(part1, sep, part2, false);
    }

    public static String join(String part1, String sep, String part2, boolean part1Required) {
        if (part1 == null || part1.length() == 0) {
            return (part1Required) ? "" : part2;
        }
        if (part2.length() == 0) {
            return part1;
        }
        return part1 + sep + part2;

    }

    /**
     * 
     * Convert an int to a string, and allow the last character to be taken off the string using pop() method.
     * 
     * e.g.
     * 1432
     * Will give 2, then 3, then 4, and finally 1 on subsequent calls to pop().
     * 
     * If there is nothing left, pop() will just return an empty string.
     * 
     */
    static class PoppableNumber {

        private int original;
        private String number;
        private int start;
        private int next;


        PoppableNumber(int value) {
            this.original = value;
            this.number = String.valueOf(value);
            this.next = number.length();
            this.start = (value < 0) ? 1 : 0;   // allow for minus sign.
        }

        boolean isNegative() {
            return (original < 0);
        }

        boolean hasMore() {
            return (next > start);
        }

        String pop() {
            return hasMore() ? number.substring(--next, next+1) : "";
        }
    }

}