数字转换成文本,未完成版

在java吧里看到这个问题,近来有空就写了写

 

import java.util.EnumMap;
import java.util.Map;

/**
* This class transfers an integer number into a string :
* <p />
* <pre>{
@code
* // an example :
* NumberText ns = NumberText.getInstance(NumberText.Lang.English);
* ns.getText(123) // one hundred and twenty-three
* ns.getOrdinalText(320) // three hundred and twentieth
* }</pre>
*
* @date 09/02/2012
*
@author na.shi.wu.you ([email protected])
*/
public abstract class NumberText {

/*----------------------------------------------------------------------------
* not designed to be inherented outside this file
* no public constructors provided, -- use factory method
---------------------------------------------------------------------------
*/
private NumberText() {}

/**
* Transfers an integer number into a String, specifically in which language
* depends on the implementation.
* <p />
* e.g. in English,
* <p />
* 100 -> one hundred
* <br />
* -976083854 -> minus nine hundred and seventy-six million and eighty-three thousand eight hundred and fifty-four
*
*
@param number the integer number to be transfered
*
@return the result String
*/
public abstract String getText(long number);

/**
* Transfers an integer number into a String of its ordinal representation,
* specifically in which language depends on the implementation.
* <p />
* e.g. in English,
* <p />
* 100 -> one hundredth
* <br />
* 8331125 -> eight million three hundred and thirty-one thousand one hundred and twenty-fifth
*
*
@param number the integer number to be transfered
*
@return the result String
*/
public abstract String getOrdinalText(long number);

/**
* There will be one NumberText implementation for each natural language.
* This Enum type is to specify a natural language, and is used as an
* argument in the factory method
* {
@link NumberText#getInstance(NumberText.Lang)}.
*/
public static enum Lang {
English, Chinese;
}

/**
* Exports a {
@code NumberText} implementation instance, based on a natural
* language argument. {
@see Lang}
*
*
@param lang
*
@return a NumberText instance.
*/
public static NumberText getInstance(Lang lang) {
if( lang == null )
throw new IllegalArgumentException("Lang cannot be null.");

NumberText result = null;
synchronized(_InstancePool) {
result = _InstancePool.get(lang);
if( result == null ) {
switch(lang) {
case English : result = new NumberTextEnglish(); break;
case Chinese : result = new NumberTextChinese(); break;
default : throw new UnsupportedOperationException(
"Language not supported yet : " + lang);
}
_InstancePool.put(lang, result);
}
}
return result;
}

private static final Map<Lang, NumberText> _InstancePool =
new EnumMap<Lang, NumberText>(Lang.class);

/*----------------------------------------------------------------------------
* English Implementation
---------------------------------------------------------------------------
*/
private static class NumberTextEnglish extends NumberText {

private static enum Power {

thousand, // 10 ^ 3
million, // 10 ^ 6
billion, // 10 ^ 9
trillion, // 10 ^ 12
quadrillion, // 10 ^ 15
quintillion, // 10 ^ 18
// long : -9,223,372,036,854,775,808 ~ +9,223,372,036,854,775,807

sextillion, // 10 ^ 21
septillion, // 10 ^ 24
octillion, // 10 ^ 27
nonillion, // 10 ^ 30
decillion, // 10 ^ 33
undecillion, // 10 ^ 36
duodecillion, // 10 ^ 39
tredecillion, // 10 ^ 42
quattuordecillion, // 10 ^ 45
quindecillion, // 10 ^ 48
sexdecillion, // 10 ^ 51
septendecillion, // 10 ^ 54
octodecillion, // 10 ^ 57
novemdecillion, // 10 ^ 60
vigintillion, // 10 ^ 63
;
}

private static enum Digit {

Zero("zero", "zeroth", "ten", ""),
One("one", "first", "eleven", "ten"),
Two("two", "second", "twelve", "twenty"),
Three("three", "third", "thirteen", "thirty"),
Four("four", "fourth", "fourteen", "fourty"),
Five("five", "fifth", "fifteen", "fifty"),
Six("six", "sixth", "sixteen", "sixty"),
Seven("seven", "seventh", "seventeen", "seventy"),
Eight("eight", "eighth", "eighteen", "eighty"),
Nine("nine", "nineth", "nineteen", "ninety");
private final String dName, oName, plusTen, multiTen;

Digit(String dName, String oName, String plusTen, String multiTen) {
this.dName = dName;
this.oName = oName;
this.plusTen = plusTen;
this.multiTen = multiTen;
}
}

@Override
public String getText(long number) {
return getStringUtil(number, false);
}

@Override
public String getOrdinalText(long number) {
String result = getStringUtil(number, true);
return result.replace("tyth", "tieth");
}

private String getStringUtil(long number, boolean isOrdinal) {
StringBuilder builder = new StringBuilder();
String numString = Long.toString(number).replace("-", "");
int power = 0;
while(numString.length() > (power + 1) * 3)
power++;
while(power > 0) {
boolean modified = extendToken(builder, numString, power * 3, isOrdinal);
if( modified )
builder.append(" ").append(Power.values()[power - 1]).append(" ");
power--;

}
boolean modified = extendToken(builder, Long.toString(number), 0,
isOrdinal);
String result = builder.toString();
if( !modified && isOrdinal )
result = result.trim() + "th";
if( number < 0 )
result = "minus " + result;
return result;
}

private boolean extendToken(StringBuilder builder,
String number,
int suffix,
boolean isOrdinal) {
assert builder != null && checkNumber(number) && suffix < number.length();

char hundred = number.length() - suffix < 3
? '0'
: number.charAt(number.length() - suffix - 3);
char ten = number.length() - suffix < 2
? '0'
: number.charAt(number.length() - suffix - 2);
int ind = number.charAt(number.length() - suffix - 1) - '0';

if( hundred == '0' && ten == '0' && ind == 0 )
return false;

if( number.length() - suffix >= 3 ) {
if( hundred != '0' )
builder.append(Digit.values()[hundred - '0'].dName).append(" hundred");
if( ten != '0' || ind > 0 )
builder.append(hundred == '0' ? "" : " ").append("and ");
else if( isOrdinal && suffix == 0 )
builder.append("th");
else
builder.append(" ");
}
switch(ten) {
case '0':
if( ind > 0 || builder.length() == 0 ) {
if( isOrdinal && suffix == 0 )
builder.append(Digit.values()[ind].oName);
else
builder.append(Digit.values()[ind].dName);
}
break;
case '1':
builder.append(Digit.values()[ind].plusTen);
if( isOrdinal && suffix == 0 )
builder.append("th");
break;
default:
builder.append(Digit.values()[ten - '0'].multiTen);
if( ind > 0 ) {
if( isOrdinal && suffix == 0 )
builder.append("-").append(Digit.values()[ind].oName);
else
builder.append("-").append(Digit.values()[ind].dName);
}
else if( isOrdinal && suffix == 0 )
builder.append("th");
break;
}

return true;
}

private boolean checkNumber(String number) {
return number != null && number.matches("[0-9]*");
}
}

/*----------------------------------------------------------------------------
* Chinese Implementation
---------------------------------------------------------------------------
*/
private static class NumberTextChinese extends NumberText {

@Override
public String getText(long number) {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public String getOrdinalText(long number) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}



你可能感兴趣的:(数字转换成文本,未完成版)