/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FenixEdu Academic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.util;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NumberToWordsConverter {
private static final Logger logger = LoggerFactory.getLogger(NumberToWordsConverter.class);
static private final String[] ONES = { "zero", "um", "dois", "três", "quatro", "cinco", "seis", "sete", "oito", "nove",
"dez", "onze", "doze", "treze", "catorze", "quinze", "dezasseis", "dezassete", "dezoito", "dezanove" };
static private final String[] ONES_EN = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "treze", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
static private final String[] TENS = { "", "", "vinte", "trinta", "quarenta", "cinquenta", "sessenta", "setenta", "oitenta",
"noventa", "cem" };
static private final String[] TENS_EN = { "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
"ninety", "hundred" };
static private final String[] HUNDREDS = { "", "cento", "duzentos", "trezentos", "quatrocentos", "quinhentos", "seiscentos",
"setecentos", "oitocentos", "novecentos", };
static private final String[] HUNDREDS_EN = { "", "hundred", "two hundred", "three hundred", "four hundred", "five hundred",
"six hundred", "seven hundred", "eight hundred", "nine hundred", };
static private final String[] THOUSAND_SINGLE = { "", "mil", "milhão", "bilião" };
static private final String[] THOUSAND_EN = { "", "thousand", "million", "billion" };
static private final String[] THOUSAND_PLURAL = { "", "mil", "milhões", "biliões" };
static private final String ZERO = ONES[0];
static private final String ZERO_EN = ONES_EN[0];
static private final String SEPARATOR = " e ";
static private final String SEPARATOR_EN = " and ";
// FIXME: locale not used yet
static public String convert(final int value) {
return convert(value, new Locale("pt", "PT"));
}
static public String convert(final int value, final Locale locale) {
if (locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
return (value == 0) ? ZERO_EN : thousandsEn(value);
}
return (value == 0) ? ZERO : thousands(value);
}
static private String ones(final int value) {
return ONES[value];
}
static private String tens(final int value) {
return (value < 20) ? ones(value) : TENS[value / 10] + ((value % 10 == 0) ? "" : SEPARATOR + ones(value % 10));
}
static private String hundreds(final int value) {
return (value <= 100) ? tens(value) : HUNDREDS[value / 100] + ((value % 100 == 0) ? "" : SEPARATOR + tens(value % 100));
}
static private String thousands(final int value) {
if (value < 1000) {
return hundreds(value);
}
int quotient = value / 1000;
int remainder = value % 1000;
return (quotient == 1) ? THOUSAND_SINGLE[quotient] + ((remainder == 0) ? "" : SEPARATOR + hundreds(remainder)) : thousands(
value, 1);
}
static private String thousands(final int value, final int level) {
if (value < 1000) {
return hundreds(value);
}
int quotient = value / 1000;
int remainder = value % 1000;
int nextRemainder = quotient % 1000;
if (nextRemainder == 0) {
return thousands(quotient, level + 1) + ((remainder == 0) ? "" : SEPARATOR + hundreds(remainder));
} else if (nextRemainder == 1) {
return thousands(quotient, level + 1) + " " + THOUSAND_SINGLE[level]
+ ((remainder == 0) ? "" : SEPARATOR + hundreds(remainder));
} else {
return thousands(quotient, level + 1) + " " + THOUSAND_PLURAL[level]
+ ((remainder == 0) ? "" : SEPARATOR + hundreds(remainder));
}
}
static private String thousandsEn(final int value) {
if (value < 1000) {
return hundredsEn(value);
}
int quotient = value / 1000;
int remainder = value % 1000;
return (quotient == 1) ? THOUSAND_EN[quotient] + ((remainder == 0) ? "" : SEPARATOR_EN + hundredsEn(remainder)) : thousandsEn(
value, 1);
}
static private String thousandsEn(final int value, final int level) {
if (value < 1000) {
return hundredsEn(value);
}
int quotient = value / 1000;
int remainder = value % 1000;
int nextRemainder = quotient % 1000;
if (nextRemainder == 0) {
return thousandsEn(quotient, level + 1) + ((remainder == 0) ? "" : SEPARATOR_EN + hundredsEn(remainder));
} else if (nextRemainder == 1) {
return thousandsEn(quotient, level + 1) + " " + THOUSAND_EN[level]
+ ((remainder == 0) ? "" : SEPARATOR_EN + hundredsEn(remainder));
} else {
return thousandsEn(quotient, level + 1) + " " + THOUSAND_EN[level]
+ ((remainder == 0) ? "" : SEPARATOR_EN + hundredsEn(remainder));
}
}
static private String hundredsEn(final int value) {
return (value <= 100) ? tensEn(value) : HUNDREDS_EN[value / 100]
+ ((value % 100 == 0) ? "" : SEPARATOR_EN + tensEn(value % 100));
}
static private String onesEn(final int value) {
return ONES_EN[value];
}
static private String tensEn(final int value) {
return (value < 20) ? onesEn(value) : TENS_EN[value / 10] + ((value % 10 == 0) ? "" : onesEn(value % 10));
}
public static void main(String[] args) {
int[] values =
new int[] { 1, 23, 52, 100, 102, 223, 1000, 1023, 2000, 2453, 9000, 10000, 10001, 11342, 100000, 1000000,
2000000, 10000000, 100000000, 1000000000 };
for (final int value : values) {
int quotient = value / 1000;
int remainder = value % 1000;
int nextRemainder = quotient % 1000;
logger.info(StringUtils.rightPad("V: " + value, 11, ' ') + "\t");
logger.info(StringUtils.rightPad("Q: " + quotient, 11, ' '));
logger.info("\tR: " + remainder);
logger.info("\tRQ: " + nextRemainder);
logger.info("\twords: " + convert(value));
}
}
}