¿Cuál es la forma más eficiente para convertir cantidad numérica dentro de palabras en inglésalgoritmo que convierte la cantidad numérica dentro de palabras en inglés
por ejemplo, 12 a doce 127 a ciento veintisiete
¿Cuál es la forma más eficiente para convertir cantidad numérica dentro de palabras en inglésalgoritmo que convierte la cantidad numérica dentro de palabras en inglés
por ejemplo, 12 a doce 127 a ciento veintisiete
Eso no llevó mucho tiempo. Esta es una implementación escrita en Java.
http://snippets.dzone.com/posts/show/3685
public class IntToEnglish {
static String[] to_19 = { "zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
static String[] tens = { "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
static String[] denom = { "",
"thousand", "million", "billion", "trillion", "quadrillion",
"quintillion", "sextillion", "septillion", "octillion", "nonillion",
"decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
"sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion" };
public static void main(String[] argv) throws Exception {
int tstValue = Integer.parseInt(argv[0]);
IntToEnglish itoe = new IntToEnglish();
System.out.println(itoe.english_number(tstValue));
/* for (int i = 0; i < 2147483647; i++) {
System.out.println(itoe.english_number(i));
} */
}
// convert a value < 100 to English.
private String convert_nn(int val) throws Exception {
if (val < 20)
return to_19[val];
for (int v = 0; v < tens.length; v++) {
String dcap = tens[v];
int dval = 20 + 10 * v;
if (dval + 10 > val) {
if ((val % 10) != 0)
return dcap + "-" + to_19[val % 10];
return dcap;
}
}
throw new Exception("Should never get here, less than 100 failure");
}
// convert a value < 1000 to english, special cased because it is the level that kicks
// off the < 100 special case. The rest are more general. This also allows you to
// get strings in the form of "forty-five hundred" if called directly.
private String convert_nnn(int val) throws Exception {
String word = "";
int rem = val/100;
int mod = val % 100;
if (rem > 0) {
word = to_19[rem] + " hundred";
if (mod > 0) {
word = word + " ";
}
}
if (mod > 0) {
word = word + convert_nn(mod);
}
return word;
}
public String english_number(int val) throws Exception {
if (val < 100) {
return convert_nn(val);
}
if (val < 1000) {
return convert_nnn(val);
}
for (int v = 0; v < denom.length; v++) {
int didx = v - 1;
int dval = new Double(Math.pow(1000, v)).intValue();
if (dval > val) {
int mod = new Double(Math.pow(1000, didx)).intValue();
int l = val/mod;
int r = val - (l * mod);
String ret = convert_nnn(l) + " " + denom[didx];
if (r > 0) {
ret = ret + ", " + english_number(r);
}
return ret;
}
}
throw new Exception("Should never get here, bottomed out in english_number");
}
}
Una forma de lograr esto sería el uso de tablas de consulta. Sería algo así como fuerza bruta, pero fácil de configurar. Por ejemplo, podría tener las palabras para 0-99 en una tabla, luego una tabla para decenas, cientos, miles, etc. Algunas matemáticas simples le darán el índice de la palabra que necesita de cada tabla.
Eso sería un gran desperdicio de memoria. – Christian
Estoy de acuerdo con su evaluación pero utilicé el término "fuerza bruta" en mi descripción. Además, hay otras respuestas para esta misma pregunta que utilizan un enfoque de tabla de búsqueda, incluida la respuesta aceptada. No estoy seguro de por qué tu comentario solo se aplica a mi respuesta. – nathan
.) Crea una biblioteca de todos los números & posiciones (por ejemplo 1 tiene otra anotación de 10, otra de 100, etc.) .) Hacer una lista de excepciones (por ejemplo, para 12) y tener en cuenta, que en su algoritmo, la misma excepción es para 112, 1012, etc.
si quiere aún más velocidad, haga un conjunto de números en caché que necesite.
Este enlace proporciona una explicación detallada de lo que parece ser un acercamiento agradable: http://www.blackwasp.co.uk/NumberToWords.aspx
Nota algunas reglas:
númerosdigit place
como "tres mil".Puede obtener el lugar de un número mediante la división de enteros planta: 532/100 -> 5
Este es un viejo código Python en mi disco duro. Puede haber errores pero debería mostrar la idea básica:
class Translator:
def transformInt(self, x):
translateNumbers(0,[str(x)])
def threeDigitsNumber(self,number):
snumber=self.twoDigitsNumber(number/100)
if number/100!=0:
snumber+=" hundred "
snumber+self.twoDigitsNumber(number)
return snumber+self.twoDigitsNumber(number)
def twoDigitsNumber(self,number):
snumber=""
if number%100==10:
snumber+="ten"
elif number%100==11:
snumber+="eleven"
elif number%100==12:
snumber+="twelve"
elif number%100==13:
snumber+="thirteen"
elif number%100==14:
snumber+="fourteen"
elif number%100==15:
snumber+="fifteen"
elif number%100==16:
snumber+="sixteen"
elif number%100==17:
snumber+="seventeen"
elif number%100==18:
snumber+="eighteen"
elif number%100==19:
snumber+="nineteen"
else:
if (number%100)/10==2:
snumber+="twenty-"
elif (number%100)/10==3:
snumber+="thirty-"
elif (number%100)/10==4:
snumber+="forty-"
elif (number%100)/10==5:
snumber+="fifty-"
elif (number%100)/10==6:
snumber+="sixty-"
elif (number%100)/10==7:
snumber+="seventy-"
elif (number%100)/10==8:
snumber+="eighty-"
elif (number%100)/10==9:
snumber+="ninety-"
if (number%10)==1:
snumber+="one"
elif (number%10)==2:
snumber+="two"
elif (number%10)==3:
snumber+="three"
elif (number%10)==4:
snumber+="four"
elif (number%10)==5:
snumber+="five"
elif (number%10)==6:
snumber+="six"
elif (number%10)==7:
snumber+="seven"
elif (number%10)==8:
snumber+="eight"
elif (number%10)==9:
snumber+="nine"
elif (number%10)==0:
if snumber!="":
if snumber[len(snumber)-1]=="-":
snumber=snumber[0:len(snumber)-1]
return snumber
def translateNumbers(self,counter,words):
if counter+1<len(words):
self.translateNumbers(counter+1,words)
else:
if counter==len(words):
return True
k=0
while k<len(words[counter]):
if (not (ord(words[counter][k])>47 and ord(words[counter][k])<58)):
break
k+=1
if (k!=len(words[counter]) or k==0):
return 1
number=int(words[counter])
from copy import copy
if number==0:
self.translateNumbers(counter+1,copy(words[0:counter]+["zero"]+words[counter+1:len(words)]))
self.next.append(copy(words[0:counter]+["zero"]+words[counter+1:len(words)]))
return 1
if number<10000:
self.translateNumbers(counter+1,copy(words[0:counter]
+self.seperatewords(self.threeDigitsNumber(number))
+words[counter+1:len(words)]))
self.next.append(copy(words[0:counter]
+self.seperatewords(self.threeDigitsNumber(number))
+words[counter+1:len(words)]))
if number>999:
snumber=""
if number>1000000000:
snumber+=self.threeDigitsNumber(number/1000000000)+" billion "
number=number%1000000000
if number>1000000:
snumber+=self.threeDigitsNumber(number/1000000)+" million "
number=number%1000000
if number>1000:
snumber+=self.threeDigitsNumber(number/1000)+" thousand "
number=number%1000
snumber+=self.threeDigitsNumber(number)
self.translateNumbers(counter+1,copy(words[0:counter]+self.seperatewords(snumber)
+words[counter+1:len(words)]))
self.next.append(copy(words[0:counter]+self.seperatewords(snumber)
+words[counter+1:len(words)]))
Esta solución no intenta dar cuenta de los espacios finales, pero es bastante rápido.
typedef const char* cstring;
using std::string;
using std::endl;
std::ostream& GetOnes(std::ostream &output, int onesValue)
{
cstring ones[] = { "zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine" };
output << ones[onesValue];
return output;
}
std::ostream& GetSubMagnitude(std::ostream &output, int subMagnitude)
{
cstring tens[] = { "zeroty", "ten", "twenty", "thirty", "fourty", "fifty",
"sixty", "seventy", "eighty", "ninety"};
if (subMagnitude/100 != 0)
{
GetOnes(output, subMagnitude/100) << " hundred ";
GetSubMagnitude(output, subMagnitude - subMagnitude/100 * 100);
}
else
{
if (subMagnitude >= 20)
{
output << tens[subMagnitude/10] << " ";
GetOnes(output, subMagnitude - subMagnitude/10 * 10);
}
else if (subMagnitude >= 10)
{
cstring teens[] = { "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen" };
output << teens[subMagnitude - 10] << " ";
}
else
{
GetOnes(output, subMagnitude) << " ";
}
}
return output;
}
std::ostream& GetLongNumber(std::ostream &output, double input)
{
cstring magnitudes[] = {"", "hundred", "thousand", "million", "billion",
"trillion"};
double magnitudeTests[] = {1, 100.0, 1000.0, 1000000.0, 1000000000.0,
1000000000000.0 };
int magTestIndex = 0;
while (floor(input/magnitudeTests[magTestIndex++]) != 0);
magTestIndex -= 2;
if (magTestIndex >= 0)
{
double subMagnitude = input/magnitudeTests[magTestIndex];
GetSubMagnitude(output, (int)subMagnitude);
if (magTestIndex) {
output << magnitudes[magTestIndex] << " ";
double remainder = input - (floor(input/
magnitudeTests[magTestIndex]) *
magnitudeTests[magTestIndex]);
if (floor(remainder) > 0)
{
GetLongNumber(output, remainder);
}
}
}
else
{
output << "zero";
}
return output;
}
Obviamente, las renuncias de responsabilidad incluyen que no cuenta para números mayores a 999,999,999,999,999, no hace fracciones y no maneja números negativos. Lo suficientemente fácil de agregar, pero tienes que parar en algún punto. –
de inicio mediante la resolución 1-99, utilizando una lista de números de 1-20, y luego 30, 40, ..., 90. A continuación, añadir cientos de conseguir 1-999. Luego use esa rutina para dar el número de cada potencia de 1,000 tan alto como desee (creo que la nomenclatura estándar más alta es para decillion, que es 10^33).
Una pequeña advertencia es que es un poco complicado conseguir los espacios en blanco en todos los casos si está tratando de comenzar y terminar sin un exceso de espacio en blanco. La solución más fácil es poner un espacio en blanco después de cada palabra, y luego quitar el espacio en blanco al terminar. Si intentas ser más preciso al construir la cuerda, es probable que termines con espacios en blanco o espacios en blanco faltantes.
Esto es part of Common Lisp!
Here's how GNU CLISP does it, y here's how CMUCL does it (más fácil de leer, en mi humilde opinión).
Haciendo un code search para "formato millonario" aparecerán muchos de ellos.
O en inglés cien ** y ** veintisiete. :) –
@Philip, el "y" es incorrecto si estás hablando del inglés correcto. "Y" es para partes fraccionales. –
@David - En inglés británico, si un número incluye un número más pequeño ** y ** se une a ellos. Como en 2010, dos mil diez. Otra variación está en la moneda cuando £ 1.20 es una libra veinte o una libra y veinte peniques. Si está aburrido puede ver http://www.english-at-home.com/speaking/saying-dates-and-numbers-in-english/ –