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