Java中使用映射继续将整数转换为单词的问题 [英] integer to word conversion in java using map continue question

查看:116
本文介绍了Java中使用映射继续将整数转换为单词的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是我在堆栈溢出中的问题的答案.

冗余代码块

       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,以找出数字的第十位.最后使用%(模数除法)找出一个位置.

我如何包含用户定义函数和切换大小写以最小化代码块.

解决方案

我建议您将单个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) : "";
        }
    }

}

This is a probable answer of my question in stack overflow.Integer to word conversion

At first I have started with dictionary. Then I came to know it is obsolete. So now I use Map instead of dictionary. My code is work well for number till Millions. But the approach I take here is a naive approach. The main problem of this code is

First: Huge numbers of variable use

2nd: Redundant code block as per program requirement

3rd: Multiple if else statement

I am thinking about this problems

Solution for 2nd problem: using user define function or macros to eliminate redundant code block

Solution for 3rd problem: Using switch case

My code:

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));
       }
   }
  }
   }

Redundant Code Blocks

       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;

This type of code block used almost every where. Taking a number divide it with 100 or 1000 to find out the hundred position then then divide it with 10 to find out the tenth position of the number. Finally using %(modular division) to find out the ones position.

How could I include user define function and switch case to minimize the code block.

解决方案

I'd suggest you break your single main method down into a couple of classes. And if you haven't already create a few unit tests to allow you to easily test / refactor things. You'll find it quicker than starting the app and reading from stdin.

You'll find it easier to deal with the number as a string. Rather than dividing by 10 all the time you just take the last character of the string. You could have a class that does that bit for you, and a separate one that does the convert.

Here's what I came up with, but I'm sure it can be improved. It has a PoppableNumber class which allows the last character of the initial number to be easily retrieved. And the NumberToString class which has a static convert method to perform the conversion.

An example of a test would be

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

And here's the NumberToString class :

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) : "";
        }
    }

}

这篇关于Java中使用映射继续将整数转换为单词的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆