import java.math.*; import java.util.Arrays; /** A class to obtain the English language name of an arbitrary precision integer or floating point number. *
This class should support all conceivable BigIntegers or BigDecimals, limited by the length of the name itself. *
This class supports short scale, long scale, and prefixed long scale naming conventions. */ public class EnglishNumberNames{ /**An ennumeration of the possible naming conventions.*/ public enum NamingConvention{SHORT_SCALE,LONG_SCALE,LONG_SCALE_PREFIXED} //Vocabulary private static final String[] smallVocabulary={"","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"}; private static final String[] largeVocabulary={"","thousand","million","billion","trillion","quadrillion","quintillion","sextillion","septillion","octillion","nonillion"}; private static final String[] largeVocabulary0={"","un","duo","tre","quattuor","quin","sex","septen","octo","novem"}; private static final String[] largeVocabulary1={"","dec","vigin","trigin","quadragin","quinquagin","sexagin","septuagin","octogin","nonagin"}; private static final String[] largeVocabulary2={"","cen","duocen","trecen","quadringen","quingen","sescen","septingen","octingen","nongen"}; //name of a number from 1 to 999 private static String shortname(int n){ n=n%1000; return (n/100>0?smallVocabulary[n/100]+" hundred":"")+(n%100>20?(n/100>0?" ":"")+smallVocabulary[((n/10)%10)+18]+(n%10>0?" ":"")+smallVocabulary[n%10]:((n/100>0&&n%100>0)?" ":"")+smallVocabulary[n%100]); } //proper word for 1000^n, in the given naming convention private static String thousandsPower(long n,NamingConvention con){ if(n<0){throw new ArithmeticException("negative powers unsupported");} if(con==NamingConvention.SHORT_SCALE||n==0||n==1){return thousandsPower(n);} else{ if(con==NamingConvention.LONG_SCALE_PREFIXED){ return ((n&1)==1?"thousand ":"")+thousandsPower((n>>>1)+1); }else{ String t=thousandsPower((n>>>1)+1); if((n&1)==1){t=t.substring(0,t.length()-2)+"ard";} return t; } } } //proper short scale word for 1000^n private static String thousandsPower(long n){ if(n<0){throw new ArithmeticException("negative powers unsupported");} if(n==0){return "";}n--; if(n<10){return largeVocabulary[(int)(n+1)];} String pow=""; String millias=""; int suffix=(int)((n/10)%10); do{ int x=(int)(n%1000); pow=largeVocabulary2[x/100]+(n==1?"":largeVocabulary0[x%10])+largeVocabulary1[(x/10)%10]+(x==0?"":millias)+pow; millias+="millia";n/=1000; }while(n>0); return pow+(suffix==1?"illion":"tillion"); } /** Returns the English short scale name for 1000^n.*/ public static String powerOf1000Name(long n){ return powerOf1000Name(n,NamingConvention.SHORT_SCALE); } /** Returns the English name for 1000^n, in the given naming convention.*/ public static String powerOf1000Name(long n,NamingConvention con){ return (n==0?"one":"one ")+thousandsPower(n,con); } /** Returns the English short scale name for 10^n.*/ public static String powerOfTenName(long n){ return powerOfTenName(n,NamingConvention.SHORT_SCALE); } /** Returns the English name for 10^n, in the given naming convention.*/ public static String powerOfTenName(long n,NamingConvention con){ if(n<0){throw new ArithmeticException("negative powers unsupported");} return (n%3==0?(n==0?"one":"one "):(n%3==1?(n==1?"ten":"ten "):(n==2?"one hundred":"one hundred ")))+thousandsPower(n/3,con); } /** Returns the English short scale name for the given BigInteger n.*/ public static String name(BigInteger n){ return name(n,0,NamingConvention.SHORT_SCALE); } /** Returns the English name for the given BigInteger n, in the given naming convention.*/ public static String name(BigInteger n,NamingConvention con){ return name(n,0,con); } /** Returns the English short scale name for the BigInteger n*1000^off. *
This method allows the naming of large numbers without storing the trailing zeroes. */ public static String name(BigInteger n,long off){ return name(n,off,NamingConvention.SHORT_SCALE); } /** Returns the English name for the BigInteger n*1000^off, in the given naming convention. *
This method allows the naming of large numbers without storing the trailing zeroes. */ public static String name(BigInteger n,long off,NamingConvention con){ if(off<0){throw new ArithmeticException("negative offset");} if(n.signum()==0){return "zero";} if(n.signum()==-1){return "negative "+name(n.negate(),off,con);} String s=""; BigInteger[] parts={n};long c=off; while(parts[0].signum()>0){ parts=n.divideAndRemainder(BigInteger.valueOf(1000)); s=(parts[0].signum()>0&&parts[1].signum()>0?" ":"")+shortname(parts[1].intValue())+(parts[1].signum()>0?(c!=0?" ":"")+thousandsPower(c,con):"")+s; n=parts[0];c++; } return s; } //base 10 digital readout of a fixed number of places (excluding trailing zeroes) for reading digits past the radix point private static String fracName(BigInteger n, int places){ if(n.signum()==0){return "";} if(n.compareTo(BigInteger.TEN.pow(places))>=0){throw new ArithmeticException("Error: Overflow");} String s=n.toString(10),f=""; int place=0; while(s.charAt(s.length()-1-place)=='0'){place++;} while(place * Examples: *

* 100 - "one hundred" *
* 1E2 - "one hundred" *
* 105 - "one hundred five" *
* 1.05E2 - "one hundred five" *
* 105.5 - "one hundred five point five" *
* 1.055E2 - "one hundred five point five" *
* 101.1 - "one hundred one point one" *
* 101.10 - "one hundred one point one" * */ public static String name(BigDecimal n){ return name(n,NamingConvention.SHORT_SCALE); } /** Returns the English name for the given BigDecimal n, in the given naming convention. Digits with a scale less than 0 are returned as base 10 digital readout. *
* Examples: *

* 100 - "one hundred" *
* 1E2 - "one hundred" *
* 105 - "one hundred five" *
* 1.05E2 - "one hundred five" *
* 105.5 - "one hundred five point five" *
* 1.055E2 - "one hundred five point five" *
* 101.1 - "one hundred one point one" *
* 101.10 - "one hundred one point one" * */ public static String name(BigDecimal n,NamingConvention con){ if(n.signum()==-1){return "negative "+name(n.negate(),con);} if(n.scale()<=0){ return name(n.unscaledValue().multiply(BigInteger.TEN.pow((-n.scale())%3)),(-n.scale())/3,con); } else{ BigInteger[] numParts=n.unscaledValue().divideAndRemainder(BigInteger.TEN.pow(n.scale())); return name(numParts[0],con)+" "+fracName(numParts[1],n.scale()); } } /** Returns the English name for the given BigDecimal n, in scientific notation. This is equivalent to name(mantissa)+" times ten to the "+name(exponent). *
* This method uses the short scale naming convention for extremely large or small exponents. *
* Examples: *

* 100 - "one times ten to the two" *
* 1E2 - "one times ten to the two" *
* 105 - "one point zero five times ten to the two" *
* 1.05E2 - "one point zero five times ten to the two" *
* 105.5 - "one point zero five five times ten to the two" *
* 1.055E2 - "one point zero five five times ten to the two" *
* 101.1 - "one point zero one one times ten to the two" *
* 101.10 - "one point zero one one times ten to the two" * */ public static String scientificName(BigDecimal n){ return scientificName(n,NamingConvention.SHORT_SCALE); } /** Returns the English name for the given BigDecimal n, in scientific notation. This is equivalent to name(mantissa)+" times ten to the "+name(exponent). *
* This method uses the given naming convention for extremely large or small exponents. *
* Examples: *

* 100 - "one times ten to the two" *
* 1E2 - "one times ten to the two" *
* 105 - "one point zero five times ten to the two" *
* 1.05E2 - "one point zero five times ten to the two" *
* 105.5 - "one point zero five five times ten to the two" *
* 1.055E2 - "one point zero five five times ten to the two" *
* 101.1 - "one point zero one one times ten to the two" *
* 101.10 - "one point zero one one times ten to the two" * */ public static String scientificName(BigDecimal n,NamingConvention con){ n=n.stripTrailingZeros(); if(n.signum()==0){return "zero";} if(n.signum()==-1){return "negative "+scientificName(n.negate(),con);} String num=n.unscaledValue().toString(); String s=""; int exp=n.precision()-n.scale()-1; for(int c=0;cDigital lengths are given without spaces. */ public static int nameLength(BigInteger n){ return name(n).replaceAll("\\s+","").length(); } /** Returns the length of the English name for the given BigInteger n, in the given naming convention. *
Digital lengths are given without spaces. */ public static int nameLength(BigInteger n,NamingConvention con){ return name(n,con).replaceAll("\\s+","").length(); } /** Returns the length of the English short scale name for the BigInteger n*1000^off. This method allows the naming of large numbers without storing the trailing zeroes. *
Digital lengths are given without spaces. */ public static int nameLength(BigInteger n,long off){ return name(n,off).replaceAll("\\s+","").length(); } /** Returns the length of the English name for the BigInteger n*1000^off, in the given naming convention. This method allows the naming of large numbers without storing the trailing zeroes. *
Digital lengths are given without spaces. */ public static int nameLength(BigInteger n,long off,NamingConvention con){ return name(n,off,con).replaceAll("\\s+","").length(); } /** Returns the length of the English short scale name for the given BigDecimal n. *
Digital lengths are given without spaces. */ public static int nameLength(BigDecimal n){ return name(n).replaceAll("\\s+","").length(); } /** Returns the length of the English name for the given BigDecimal n, in the given naming convention. *
Digital lengths are given without spaces. */ public static int nameLength(BigDecimal n,NamingConvention con){ return name(n,con).replaceAll("\\s+","").length(); } /** Returns the length of the English name for the given BigDecimal n, in scientific notation (exponent specified in short scale). *
Digital lengths are given without spaces. */ public static int scientificNameLength(BigDecimal n){ return scientificName(n).replaceAll("\\s+","").length(); } /** Returns the length of the English name for the given BigDecimal n, in scientific notation (exponent specified in the given naming convention). *
Digital lengths are given without spaces. */ public static int scientificNameLength(BigDecimal n,NamingConvention con){ return scientificName(n,con).replaceAll("\\s+","").length(); } public static void main(String[] args){ } }