How to convert number to words in java

前端 未结 27 2792
遇见更好的自我
遇见更好的自我 2020-11-21 23:53

We currently have a crude mechanism to convert numbers to words (e.g. using a few static arrays) and based on the size of the number translating that into an english text. B

相关标签:
27条回答
  • 2020-11-22 00:33
    public class NumberConverter {
    
        private String[] singleDigit = {"", " one", " two", " three",
        " four", " five"," six", " seven", " eight", " nine"};
    
        private String[] tens = {" ten", " eleven", " twelve", " thirteen",
                " fourteen", " fifteen"," sixteen", " seventeen", " eighteen", " nineteen"};
    
        private String[] twoDigits = {"", "", " twenty", " thirty",
                " forty", " fifty"," sixty", " seventy", " eighty", " ninety"};
    
        public String convertToWords(String input) {
            long number = Long.parseLong(input);
            int size = input.length();
            if (size <= 3) {
                int num = (int) number;
                return handle3Digits(num);
            } else if (size > 3 && size <= 6) {
                int thousand = (int)(number/1000);
                int hundred = (int) (number % 1000);
                String thousands = handle3Digits(thousand);
    
                String hundreds = handle3Digits(hundred);
                String word = "";
    
                if (!thousands.isEmpty()) {
                    word = thousands +" thousand";
                }
                word += hundreds;
                return word;
            } else if (size > 6 && size <= 9) {
                int million = (int) (number/ 1000000);
                number = number % 1000000;
                int thousand = (int)(number/1000);
                int hundred = (int) (number % 1000);
    
                String millions = handle3Digits(million);
                String thousands = handle3Digits(thousand);
                String hundreds = handle3Digits(hundred);
    
                String word = "";
    
                if (!millions.isEmpty()) {
                    word = millions +" million";
                }
                if (!thousands.isEmpty()) {
                    word += thousands +" thousand";
                }
                word += hundreds;
                return word;
            }
    
            return "Not implemented yet.";
        }
    
    
        private String handle3Digits(int number) {
            if (number <= 0)
                return "";
    
            String word = "";
            if (number/100 > 0) {
                int dividend = number/100;
                word = singleDigit[dividend] + " hundred";
                number = number % 100;
            }
            if (number/10 > 1) {
                int dividend = number/10;
                number = number % 10;
                word += twoDigits[dividend];
            } else if (number/10 == 1) {
                number = number % 10;
                word += tens[number];
                return word;
            } else {
                number = number % 10;
            }
            if (number > 0) {
                word += singleDigit[number];
            }
    
            return word;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 00:34

    I think that this solution is not the best, since it works only for int, but i think it's great for a beginner.

    public class NumberWordConverter {
        public static final String[] units = {
                "", "one", "two", "three", "four", "five", "six", "seven",
                "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
                "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
        };
    
        public static final String[] tens = {
                "",        // 0
                "",        // 1
                "twenty",  // 2
                "thirty",  // 3
                "forty",   // 4
                "fifty",   // 5
                "sixty",   // 6
                "seventy", // 7
                "eighty",  // 8
                "ninety"   // 9
        };
    
        public static String convert(final int n) {
            if (n < 0) {
                return "minus " + convert(-n);
            }
    
            if (n < 20) {
                return units[n];
            }
    
            if (n < 100) {
                return tens[n / 10] + ((n % 10 != 0) ? " " : "") + units[n % 10];
            }
    
            if (n < 1000) {
                return units[n / 100] + " hundred" + ((n % 100 != 0) ? " " : "") + convert(n % 100);
            }
    
            if (n < 1000000) {
                return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "") + convert(n % 1000);
            }
    
            if (n < 1000000000) {
                return convert(n / 1000000) + " million" + ((n % 1000000 != 0) ? " " : "") + convert(n % 1000000);
            }
    
            return convert(n / 1000000000) + " billion"  + ((n % 1000000000 != 0) ? " " : "") + convert(n % 1000000000);
        }
    
        public static void main(final String[] args) {
            final Random generator = new Random();
    
            int n;
            for (int i = 0; i < 20; i++) {
                n = generator.nextInt(Integer.MAX_VALUE);
    
                System.out.printf("%10d = '%s'%n", n, convert(n));
            }
    
            n = 1000;
            System.out.printf("%10d = '%s'%n", n, convert(n));
    
            n = 2000;
            System.out.printf("%10d = '%s'%n", n, convert(n));
    
            n = 10000;
            System.out.printf("%10d = '%s'%n", n, convert(n));
    
            n = 11000;
            System.out.printf("%10d = '%s'%n", n, convert(n));
    
            n = 999999999;
            System.out.printf("%10d = '%s'%n", n, convert(n));
    
            n = Integer.MAX_VALUE;
            System.out.printf("%10d = '%s'%n", n, convert(n));
        }
    }
    

    The test creates 20 random numbers up to Integer.MAX_VALUE and than some that know to be problematic, because of 0, 10, etc.. Output:

       5599908 = 'five million five hundred ninety nine thousand nine hundred eight'
     192603486 = 'one hundred ninety two million six hundred three thousand four hundred eighty six'
    1392431868 = 'one billion three hundred ninety two million four hundred thirty one thousand eight hundred sixty eight'
    1023787010 = 'one billion twenty three million seven hundred eighty seven thousand ten'
    1364396236 = 'one billion three hundred sixty four million three hundred ninety six thousand two hundred thirty six'
    1511255671 = 'one billion five hundred eleven million two hundred fifty five thousand six hundred seventy one'
     225955221 = 'two hundred twenty five million nine hundred fifty five thousand two hundred twenty one'
    1890141052 = 'one billion eight hundred ninety million one hundred forty one thousand fifty two'
     261839422 = 'two hundred sixty one million eight hundred thirty nine thousand four hundred twenty two'
     728428650 = 'seven hundred twenty eight million four hundred twenty eight thousand six hundred fifty'
     860607319 = 'eight hundred sixty million six hundred seven thousand three hundred nineteen'
     719753587 = 'seven hundred nineteen million seven hundred fifty three thousand five hundred eighty seven'
    2063829124 = 'two billion sixty three million eight hundred twenty nine thousand one hundred twenty four'
    1081010996 = 'one billion eighty one million ten thousand nine hundred ninety six'
     999215799 = 'nine hundred ninety nine million two hundred fifteen thousand seven hundred ninety nine'
    2105226236 = 'two billion one hundred five million two hundred twenty six thousand two hundred thirty six'
    1431882940 = 'one billion four hundred thirty one million eight hundred eighty two thousand nine hundred forty'
    1991707241 = 'one billion nine hundred ninety one million seven hundred seven thousand two hundred forty one'
    1088301563 = 'one billion eighty eight million three hundred one thousand five hundred sixty three'
     964601609 = 'nine hundred sixty four million six hundred one thousand six hundred nine'
          1000 = 'one thousand'
          2000 = 'two thousand'
         10000 = 'ten thousand'
         11000 = 'eleven thousand'
     999999999 = 'nine hundred ninety nine million nine hundred ninety nine thousand nine hundred ninety nine'
    2147483647 = 'two billion one hundred forty seven million four hundred eighty three thousand six hundred forty seven'
    

    Hope it helps :)

    0 讨论(0)
  • 2020-11-22 00:35

    Here is the code, I don't think there is any method in SE.

    It basically converts number to string and parses String and associates it with the weight

    for example

    1000
    

    1 is treated as thousand position and 1 gets mapped to "one" and thousand because of position


    This is the code from the website:

    English

    import java.text.DecimalFormat;
    
    public class EnglishNumberToWords {
    
      private static final String[] tensNames = {
        "",
        " ten",
        " twenty",
        " thirty",
        " forty",
        " fifty",
        " sixty",
        " seventy",
        " eighty",
        " ninety"
      };
    
      private static final String[] numNames = {
        "",
        " one",
        " two",
        " three",
        " four",
        " five",
        " six",
        " seven",
        " eight",
        " nine",
        " ten",
        " eleven",
        " twelve",
        " thirteen",
        " fourteen",
        " fifteen",
        " sixteen",
        " seventeen",
        " eighteen",
        " nineteen"
      };
    
      private EnglishNumberToWords() {}
    
      private static String convertLessThanOneThousand(int number) {
        String soFar;
    
        if (number % 100 < 20){
          soFar = numNames[number % 100];
          number /= 100;
        }
        else {
          soFar = numNames[number % 10];
          number /= 10;
    
          soFar = tensNames[number % 10] + soFar;
          number /= 10;
        }
        if (number == 0) return soFar;
        return numNames[number] + " hundred" + soFar;
      }
    
    
      public static String convert(long number) {
        // 0 to 999 999 999 999
        if (number == 0) { return "zero"; }
    
        String snumber = Long.toString(number);
    
        // pad with "0"
        String mask = "000000000000";
        DecimalFormat df = new DecimalFormat(mask);
        snumber = df.format(number);
    
        // XXXnnnnnnnnn
        int billions = Integer.parseInt(snumber.substring(0,3));
        // nnnXXXnnnnnn
        int millions  = Integer.parseInt(snumber.substring(3,6));
        // nnnnnnXXXnnn
        int hundredThousands = Integer.parseInt(snumber.substring(6,9));
        // nnnnnnnnnXXX
        int thousands = Integer.parseInt(snumber.substring(9,12));
    
        String tradBillions;
        switch (billions) {
        case 0:
          tradBillions = "";
          break;
        case 1 :
          tradBillions = convertLessThanOneThousand(billions)
          + " billion ";
          break;
        default :
          tradBillions = convertLessThanOneThousand(billions)
          + " billion ";
        }
        String result =  tradBillions;
    
        String tradMillions;
        switch (millions) {
        case 0:
          tradMillions = "";
          break;
        case 1 :
          tradMillions = convertLessThanOneThousand(millions)
             + " million ";
          break;
        default :
          tradMillions = convertLessThanOneThousand(millions)
             + " million ";
        }
        result =  result + tradMillions;
    
        String tradHundredThousands;
        switch (hundredThousands) {
        case 0:
          tradHundredThousands = "";
          break;
        case 1 :
          tradHundredThousands = "one thousand ";
          break;
        default :
          tradHundredThousands = convertLessThanOneThousand(hundredThousands)
             + " thousand ";
        }
        result =  result + tradHundredThousands;
    
        String tradThousand;
        tradThousand = convertLessThanOneThousand(thousands);
        result =  result + tradThousand;
    
        // remove extra spaces!
        return result.replaceAll("^\\s+", "").replaceAll("\\b\\s{2,}\\b", " ");
      }
    
      /**
       * testing
       * @param args
       */
      public static void main(String[] args) {
        System.out.println("*** " + EnglishNumberToWords.convert(0));
        System.out.println("*** " + EnglishNumberToWords.convert(1));
        System.out.println("*** " + EnglishNumberToWords.convert(16));
        System.out.println("*** " + EnglishNumberToWords.convert(100));
        System.out.println("*** " + EnglishNumberToWords.convert(118));
        System.out.println("*** " + EnglishNumberToWords.convert(200));
        System.out.println("*** " + EnglishNumberToWords.convert(219));
        System.out.println("*** " + EnglishNumberToWords.convert(800));
        System.out.println("*** " + EnglishNumberToWords.convert(801));
        System.out.println("*** " + EnglishNumberToWords.convert(1316));
        System.out.println("*** " + EnglishNumberToWords.convert(1000000));
        System.out.println("*** " + EnglishNumberToWords.convert(2000000));
        System.out.println("*** " + EnglishNumberToWords.convert(3000200));
        System.out.println("*** " + EnglishNumberToWords.convert(700000));
        System.out.println("*** " + EnglishNumberToWords.convert(9000000));
        System.out.println("*** " + EnglishNumberToWords.convert(9001000));
        System.out.println("*** " + EnglishNumberToWords.convert(123456789));
        System.out.println("*** " + EnglishNumberToWords.convert(2147483647));
        System.out.println("*** " + EnglishNumberToWords.convert(3000000010L));
    
        /*
         *** zero
         *** one
         *** sixteen
         *** one hundred
         *** one hundred eighteen
         *** two hundred
         *** two hundred nineteen
         *** eight hundred
         *** eight hundred one
         *** one thousand three hundred sixteen
         *** one million
         *** two millions
         *** three millions two hundred
         *** seven hundred thousand
         *** nine millions
         *** nine millions one thousand
         *** one hundred twenty three millions four hundred
         **      fifty six thousand seven hundred eighty nine
         *** two billion one hundred forty seven millions
         **      four hundred eighty three thousand six hundred forty seven
         *** three billion ten
         **/
      }
    }
    

    Français Quite different than the english version but french is a lot more difficult!

    package com.rgagnon.howto;
    
    import java.text.*;
    
    class FrenchNumberToWords {
      private static final String[] dizaineNames = {
        "",
        "",
        "vingt",
        "trente",
        "quarante",
        "cinquante",
        "soixante",
        "soixante",
        "quatre-vingt",
        "quatre-vingt"
      };
    
      private static final String[] uniteNames1 = {
        "",
        "un",
        "deux",
        "trois",
        "quatre",
        "cinq",
        "six",
        "sept",
        "huit",
        "neuf",
        "dix",
        "onze",
        "douze",
        "treize",
        "quatorze",
        "quinze",
        "seize",
        "dix-sept",
        "dix-huit",
        "dix-neuf"
      };
    
      private static final String[] uniteNames2 = {
        "",
        "",
        "deux",
        "trois",
        "quatre",
        "cinq",
        "six",
        "sept",
        "huit",
        "neuf",
        "dix"
      };
    
      private FrenchNumberToWords() {}
    
      private static String convertZeroToHundred(int number) {
    
        int laDizaine = number / 10;
        int lUnite = number % 10;
        String resultat = "";
    
        switch (laDizaine) {
        case 1 :
        case 7 :
        case 9 :
          lUnite = lUnite + 10;
          break;
        default:
        }
    
        // séparateur "-" "et"  ""
        String laLiaison = "";
        if (laDizaine > 1) {
          laLiaison = "-";
        }
        // cas particuliers
        switch (lUnite) {
        case 0:
          laLiaison = "";
          break;
        case 1 :
          if (laDizaine == 8) {
            laLiaison = "-";
          }
          else {
            laLiaison = " et ";
          }
          break;
        case 11 :
          if (laDizaine==7) {
            laLiaison = " et ";
          }
          break;
        default:
        }
    
        // dizaines en lettres
        switch (laDizaine) {
        case 0:
          resultat = uniteNames1[lUnite];
          break;
        case 8 :
          if (lUnite == 0) {
            resultat = dizaineNames[laDizaine];
          }
          else {
            resultat = dizaineNames[laDizaine]
                                    + laLiaison + uniteNames1[lUnite];
          }
          break;
        default :
          resultat = dizaineNames[laDizaine]
                                  + laLiaison + uniteNames1[lUnite];
        }
        return resultat;
      }
    
      private static String convertLessThanOneThousand(int number) {
    
        int lesCentaines = number / 100;
        int leReste = number % 100;
        String sReste = convertZeroToHundred(leReste);
    
        String resultat;
        switch (lesCentaines) {
        case 0:
          resultat = sReste;
          break;
        case 1 :
          if (leReste > 0) {
            resultat = "cent " + sReste;
          }
          else {
            resultat = "cent";
          }
          break;
        default :
          if (leReste > 0) {
            resultat = uniteNames2[lesCentaines] + " cent " + sReste;
          }
          else {
            resultat = uniteNames2[lesCentaines] + " cents";
          }
        }
        return resultat;
      }
    
      public static String convert(long number) {
        // 0 à 999 999 999 999
        if (number == 0) { return "zéro"; }
    
        String snumber = Long.toString(number);
    
        // pad des "0"
        String mask = "000000000000";
        DecimalFormat df = new DecimalFormat(mask);
        snumber = df.format(number);
    
        // XXXnnnnnnnnn
        int lesMilliards = Integer.parseInt(snumber.substring(0,3));
        // nnnXXXnnnnnn
        int lesMillions  = Integer.parseInt(snumber.substring(3,6));
        // nnnnnnXXXnnn
        int lesCentMille = Integer.parseInt(snumber.substring(6,9));
        // nnnnnnnnnXXX
        int lesMille = Integer.parseInt(snumber.substring(9,12));
    
        String tradMilliards;
        switch (lesMilliards) {
        case 0:
          tradMilliards = "";
          break;
        case 1 :
          tradMilliards = convertLessThanOneThousand(lesMilliards)
             + " milliard ";
          break;
        default :
          tradMilliards = convertLessThanOneThousand(lesMilliards)
             + " milliards ";
        }
        String resultat =  tradMilliards;
    
        String tradMillions;
        switch (lesMillions) {
        case 0:
          tradMillions = "";
          break;
        case 1 :
          tradMillions = convertLessThanOneThousand(lesMillions)
             + " million ";
          break;
        default :
          tradMillions = convertLessThanOneThousand(lesMillions)
             + " millions ";
        }
        resultat =  resultat + tradMillions;
    
        String tradCentMille;
        switch (lesCentMille) {
        case 0:
          tradCentMille = "";
          break;
        case 1 :
          tradCentMille = "mille ";
          break;
        default :
          tradCentMille = convertLessThanOneThousand(lesCentMille)
             + " mille ";
        }
        resultat =  resultat + tradCentMille;
    
        String tradMille;
        tradMille = convertLessThanOneThousand(lesMille);
        resultat =  resultat + tradMille;
    
        return resultat;
      }
    
      public static void main(String[] args) {
        System.out.println("*** " + FrenchNumberToWords.convert(0));
        System.out.println("*** " + FrenchNumberToWords.convert(9));
        System.out.println("*** " + FrenchNumberToWords.convert(19));
        System.out.println("*** " + FrenchNumberToWords.convert(21));
        System.out.println("*** " + FrenchNumberToWords.convert(28));
        System.out.println("*** " + FrenchNumberToWords.convert(71));
        System.out.println("*** " + FrenchNumberToWords.convert(72));
        System.out.println("*** " + FrenchNumberToWords.convert(80));
        System.out.println("*** " + FrenchNumberToWords.convert(81));
        System.out.println("*** " + FrenchNumberToWords.convert(89));
        System.out.println("*** " + FrenchNumberToWords.convert(90));
        System.out.println("*** " + FrenchNumberToWords.convert(91));
        System.out.println("*** " + FrenchNumberToWords.convert(97));
        System.out.println("*** " + FrenchNumberToWords.convert(100));
        System.out.println("*** " + FrenchNumberToWords.convert(101));
        System.out.println("*** " + FrenchNumberToWords.convert(110));
        System.out.println("*** " + FrenchNumberToWords.convert(120));
        System.out.println("*** " + FrenchNumberToWords.convert(200));
        System.out.println("*** " + FrenchNumberToWords.convert(201));
        System.out.println("*** " + FrenchNumberToWords.convert(232));
        System.out.println("*** " + FrenchNumberToWords.convert(999));
        System.out.println("*** " + FrenchNumberToWords.convert(1000));
        System.out.println("*** " + FrenchNumberToWords.convert(1001));
        System.out.println("*** " + FrenchNumberToWords.convert(10000));
        System.out.println("*** " + FrenchNumberToWords.convert(10001));
        System.out.println("*** " + FrenchNumberToWords.convert(100000));
        System.out.println("*** " + FrenchNumberToWords.convert(2000000));
        System.out.println("*** " + FrenchNumberToWords.convert(3000000000L));
        System.out.println("*** " + FrenchNumberToWords.convert(2147483647));
        /*
         *** OUTPUT
         *** zéro
         *** neuf
         *** dix-neuf
         *** vingt et un
         *** vingt-huit
         *** soixante et onze
         *** soixante-douze
         *** quatre-vingt
         *** quatre-vingt-un
         *** quatre-vingt-neuf
         *** quatre-vingt-dix
         *** quatre-vingt-onze
         *** quatre-vingt-dix-sept
         *** cent
         *** cent un
         *** cent dix
         *** cent vingt
         *** deux cents
         *** deux cent un
         *** deux cent trente-deux
         *** neuf cent quatre-vingt-dix-neuf
         *** mille
         *** mille un
         *** dix mille
         *** dix mille un
         *** cent mille
         *** deux millions
         *** trois milliards
         *** deux milliards cent quarante-sept millions
         **          quatre cent quatre-vingt-trois mille six cent quarante-sept
         */
      }
    }
    

    You can handle "dollar and cent" conversion by calling the "convert" method two times.

    String phrase = "12345.67" ;
    Float num = new Float( phrase ) ;
    int dollars = (int)Math.floor( num ) ;
    int cent = (int)Math.floor( ( num - dollars ) * 100.0f ) ;
    
    String s = "$ " + EnglishNumberToWords.convert( dollars ) + " and "
               + EnglishNumberToWords.convert( cent ) + " cents" ;
    

    Another way to use a built-in function of your DBMS (if available). For Oracle

    SQL> select to_char(to_date(873,'J'), 'JSP') as converted_form from dual;
    
    CONVERTED_FORM
    ---------------------------
    EIGHT HUNDRED SEVENTY-THREE
    
    SQL>
    'JSP' means :
    J : the Julian format.
    SP : spells the word for the number passed to to_date
    
    0 讨论(0)
  • 2020-11-22 00:35

    ICU4J contains nice number-spellout support. The files with the "rules" can be easily edited, and it's no problem to add other languages (we did it e.g. for Polish and Russian).

    0 讨论(0)
  • 2020-11-22 00:35
    package it.tommasoresti.facebook;
    
    class NumbersToWords {
    
        private static final String ZERO = "zero";
        private static String[] oneToNine = {
                "one", "two", "three", "four", "five", "six", "seven", "height", "nine"
        };
    
        private static String[] tenToNinteen = {
                "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
        };
    
        private static String[] dozens = {
                "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
        };
    
        public static String solution(int number) {
            if(number == 0)
                return ZERO;
    
            return generate(number).trim();
        }
    
        public static String generate(int number) {
            if(number >= 1000000000) {
                return generate(number / 1000000000) + " billion " + generate(number % 1000000000);
            }
            else if(number >= 1000000) {
                return generate(number / 1000000) + " million " + generate(number % 1000000);
            }
            else if(number >= 1000) {
                return generate(number / 1000) + " thousand " + generate(number % 1000);
            }
            else if(number >= 100) {
                return generate(number / 100) + " hundred " + generate(number % 100);
            }
    
            return generate1To99(number);
        }
    
        private static String generate1To99(int number) {
            if (number == 0)
                return "";
    
            if (number <= 9)
                return oneToNine[number - 1];
            else if (number <= 19)
                return tenToNinteen[number % 10];
            else {
                return dozens[number / 10 - 1] + " " + generate1To99(number % 10);
            }
        }
    }
    

    Test

    @Test
    public void given_a_complex_number() throws Exception {
        assertThat(solution(1234567890),
            is("one billion two hundred thirty four million five hundred sixty seven thousand height hundred ninety"));
    }
    
    0 讨论(0)
  • 2020-11-22 00:37

    You probably don't need this any more, but I recently wrote a java class to do this. Apparently Yanick Rochon did something similar. It will convert numbers up to 999 Novemdecillion (999*10^60). It could do more if I knew what came after Novemdecillion, but I would be willing to bet it's unnecessary. Just feed the number as a string in cents. The output is also grammatically correct.

    Here is a link to the Bitbucket Repo

    0 讨论(0)
提交回复
热议问题