Escribir números con letras

Detalles

altCon éste escueto título pretendemos presentar un algoritmo tal que dada una cantidad numérica entera y positiva sea capaz de expresarla con texto, es decir, tal y como la leemos.

Este tipo de algoritmos se utiliza, por ejemplo, en la emisión de cheques bancarios y otros documentos en los que se escriben cifras como método adicional para evitar errores y/o falsificaciones. También se utilizan en aplicaciones de síntesis de voz, en los cuales puede ser necesario "leer" las cifras.

Vamos ahondar un poco más en el tema y a descubrir los problemas a los que nos enfrentamos

 

En principio, no es un algoritmo complicado, ya que el sistema que utilizamos para leer las cifras está basado en dar nombre a las unidades, decenas y centenas (con lo que podemos leer los nombres de cualquier números de tres cifras) y a partir de ahí utilizar agrupaciones de tres en tres (miles) y de seis en seis (millones, billones, etc...). Es decir, podemos encontrar una estructura regular en la forma de leer los números.

Sin embargo, hacerlo relativamente bien en español no es tan sencillo (comparado con idiomas como el inglés, por ejemplo), ya que por un lado se utiliza una enorme cantidad de irregularidades (por ejemplo, números con nombre propio, como el doce, que si tuviera un nombre regular debería llamarse diez y dos" y de estos tenemos un montón -del once al veintinueve-) y por otro lado, el hecho de que en español los números pueden actuar tanto de pronombre como de determinante, y en éste último caso, tanto femenino como masculino (Ejemplo: 761 puede actuar como pronombre: "Setecientos sesenta y uno", como determinante masculino: "Setecientos sesenta y un euros", o femenino: "Setecientas sesenta y una libras esterlinas").

Empecemos por el hecho de que una cantidad escrita puede actuar como pronombre, o como determinante. (Aquí me han ayudado. Gracias kitty ;-).

  • Los determinantes son una clase de palabras muy heterogéneas, pero en general, y simplificando mucho, podríamos decir que acompañan siempre a un nombre, a un sustantivo, haciendo más preciso su significado. En español, cuando los números actúan de determinante tienen género, el mismo del sustantivo al que acompañan. Quizá el determinante más sencillo de este tipo sea el del número 1: Ejemplos: Una jirafa, un león.
    Pero lo mismo ocurre si el número es otro:
    • Doscientas veintiuna jirafas
    • Doscientos veintiún leones
  • Los pronombres son palabras -al igual que antes, simplificando mucho- que pueden tomar el papel de un sustativo. En el caso de los números, representan al propio nombre del número.
    Por ejemplo:
    • ¿En qué año naciste? En mil novecientos cuarenta y uno (Fíjate: ni "cuarenta y un" ni "cuarenta y una")
    • ¿Qué número ha salido premiado en la lotería de ayer?: El treinta y seis mil setecientos ochenta y uno.

El segundo tema son las irregularidades. (Nota: al hablar de la primera, segunda, tercera... cifras de un número empezamos a contar por la derecha, la menos significativa, la unidad. Es decir, la primera es la unidad, la segunda la decena... etc.)

  • Las cifras básicas (unidades) tienen nombre: uno, dos, tres... hasta el nueve. Las decenas también: diez, veinte, treinta... hasta el noventa. La regla general dice que un número de dos cifras se forma con el nombre de la decena, la conjunción "y" y el nombre de la unidad. Por ejemplo, el 38: "treinta y ocho", pero esto no es cierto para los números 11 a 19 y 21 a 29, que tienen nombre propio: once, doce, trece, catorce, quince.... y veintiuno, veintidós, veintitrés... hasta el veintinueve. Pero no sólo eso, en los que terminan en 1, la expresión del número cambia según actúen de determinante masculino, femenino o pronombre. Ejemplo: veintiún, veintiuna, veintiuno. También hay que poner ojo a las tildes: un, dos y tres no llevan tilde, y tampoco "treinta y un", "treinta y dos" y "treinta y tres", pero sí llevan "veintiún", "veintidós" y "veintitrés".
  • Las centenas también tienen nombre propio: cien, doscientos, trescientos, cuatrocientos... pero también cambian cuando el número actua de determinante femenino por un lado (ej: trescientas) o de determinante masculino o pronombre por otro (trescientos). El cien es otra excepción... cuando la cifra es exactamete 100 se llama "cien", y si no es así "ciento".
  • A partir de la cuarta cifra hasta la sexta se repite el mismo esquema que de la 1ª a la 3ª. Basta con agregar la partícula "mil"... pero también hay irregularidades. Aquí ya no importa si el número actúa como pronombre. Las cifras 4ª a 6ª forman en sí mismas un número que es determinante del "mil". Pero ese "mil" se interpreta como masculino si toda la cifra está actuando como pronombre o determinante masculino, y como femenino si toda la cifra está actuando como determinante femenino. Ej: 721000: Setecientas veintiuna mil (det. femenino) o 721000: Setecientos veintiún mil (determinante masculino o pronombre).
  • Hay otra excepción más relacionada con las cifras 4ª a 6ª: si la cantidad que representan es exactamente 1, no se menciona, y sólo se pone la partícula "mil", en lugar de "un mil". Ej: 1200 pesetas: mil doscientas pesetas (en lugar de una mil doscentas pesetas). 101200: ciento una mil doscientas pesetas.
  • A partir de la 7ª cifra y hasta la 12ª podemos repetir el mismo proceso que hacemos con las cifras 1ª a 6ª. De hecho, este esquema se vuelve a repetir cada 6 cifras (de la 13ª a la 18ª, de la 19ª a la 24ª...) Ya sabemos que las cifras 7ª a 12ª representan millones... Pero:
    • Esas cifras actúan como determinante de los millones (y no de todo el número), y por lo tanto, tienen género másculino.
    • Los millones tienen número: singular cuando es exactamente un millón, y plural cuando son dos o más millones.
  • Las siguientes agrupaciones de seis cifras determinan a los billones (cifras 13ª a 18ª), trillones (cifras 19ª a 24ª) y cuatrillones (25ª a 30ª) con ls mismas reglas que para los millones. Más allá de eso, no se suelen leer las cifras.

Por último, una puntualización. En el mundo de habla inglesa, la palabra "billion" equivale a los "mil millones" en español, y la palabra "trillion" equivale al "billón" en español... (también ocurre algo similar en ruso, griego y brasileño). Es lo que llaman la "escala corta", en la que los grupos de cifras más grandes se hacen de tres en tres en lugar de de seis en seis (la "escala larga" que se utiliza en español y el resto de idiomas). Hay voces que dicen que eso provoca confusión, y han propuesto la utilización en español de extraños palabros como "millardo" y la escala corta de numeración también en español. Por supuesto que sería fantástico que todos los paises de mundo utilizaramos una forma similar de nombrar a los números... pero de momento no la hay.... cada lengua tiene su propia forma de leer los números basada en la escala corta o en la larga... pero un número es siempre el mismo número, se lea en un idioma o en otro. Las confusiones que yo he notado siempre han sido por parte de medios de comunicación en los que algún zoquete que no sabe ni inglés ni español ni conoce las culturas de las cuales está traduciendo ha traducido una cifra de cualquier manera... así que personalmente me parece absolutamente prescindible cualquier otro matiz al respecto... las cifras en unos idiomas se leen de una manera, y en otros de otra. En español, y mientras ninguna voz absolutamente autorizada (ja!) diga lo contrario, utilizamos la escala larga.

Pero vamos con el algoritmo. En esta ocasión, vamos a construir una clase en C#, a la que le vamos a colocar un método estático public static String Convierte(String s, Tipo t), siendo Tipo un enumerado de tres elementos: public enum Tipo {Pronombre, DetMasculino, DetFemenino};

Al método Convierte le pasaremos una cadena de hasta 30 carácteres, que contendrá la representación de un número con cifras de "0" a "9", sin puntos ni comas ni espacios ni ningún otro símbolo. Éste método devolverá la representación del número escrito, y dependiendo del segundo parámetro, como determinante masculino o femenino, o como pronombre.

Para ello, vamos a apoyarnos en una serie de métodos privados.

  • El método private static bool EsNumero(String s) simplemente nos dirá si la cadena s está formada exclusivamente por carácteres del "0" al "9".
  • El método private static String ConvierteTodo(int i, Tipo t) tomará la cadena y la irá descomponiendo de seis en seis cifras, empezando por las menos significativas, y se las irá pasando al método Convierte6. Éste devolverá el texto correspondiente a esas seis cifras, y de vuelta en ConvierteTodo, se añadirán las particulas correspondientes a millones, billones, trillones y cuatrillones. Se tiene en cuenta que las primeras seis cifras menos significativas actúan como indica la variable "Tipo t", y que los siguientes grupos de seis son determinantes masculinos de "millones", "billones", etc. Se tiene también en cuenta el número (millón vs. millones).
  • El método private static String Convierte6(int i, Tipo t) se encargará de devolver el nombre correspondiente a un grupo de seis cifras, teniendo en cuenta cómo actúa este grupo, según el parámetro t. El proceso consiste en descomponer el grupo de seis en dos partes de tres cifras, y pasar cada parte al método Convierte3. Entre las dos partes que devuelva Convierte3 se insertará la partícula "mil" teniendo en cuenta las irregularidades comentadas.
  • El método private static String Convierte3(int i, Tipo t) se encargará de devolver el nombre correspondiente a un grupo de tres cifras (centenas-decenas-unidades). Se encarga de las irregularidades de las centenas y se apoya en el método Convierte2 para las decenas y las unidades.
  • El método private static String Convierte2(int i, Tipo t) toma un grupo de dos cifras y devuelve su nombre escrito, teniendo en cuenta los nombres propios de los números 10 a 29. Se apoya en Convierte1.
  • Por último, el método private static String Convierte1(int i, Tipo t) simplemente toma un número de una cifra y lo devuelve escrito.

Poco más... el resto es puramente trivial. Aquí tienes la clase entera, úsala como quieras.

En esta ocasión, el código está tanto en c# como en java.

csharp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
 * Clase en C# para convertir números a su equivalente escrito.
 * Utilización: pásale al método público "Convierte" una cadena
 * de hasta 30 carácteres con la representación del número en cifras, y la
 * forma en la que debe actuar el número, como Pronombre, o como determinante
 * masculino o femenino, mediante un valor del enumerado Tipo, y te devolverá
 * una cadena con el número como texto.
 * 
 * Ejemplo:
 * Console.WriteLine(NumLetras.Convierte("12312343",NumLetras.Tipo.Pronombre));
 * 
 * Puedes usar, modificar y distribuir libremente éste código, teniendo en cuenta
 * que se distribuye "tal cual", sin garantía ni responsabilidad de ningún tipo.
 * Si te resulta util, se agradece un link a "www.latecladeescape.com".
 * 
 * Éste código se acoge los términos de la licencia descrita a continuación en inglés
 * y su utilización de cualquier tipo supone la aceptación de dichos términos.
 * 
 * **************************************************************************
 * Copyright © 2007 by La tecla de ESCAPE <www.latecladeescape.com>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ****************************************************************************
 * @version 1.0
 * 
 */
 
using System;
using System.Collections.Generic;
using System.Text;
 
 
    class NumLetras
    {
        public enum Tipo {Pronombre, DetMasculino, DetFemenino};
 
        private static String[] nombresIrregulares ={
        "", "uno", "dos", "tres", "cuatro",
        "cinco", "seis", "siete", "ocho", "nueve",
        "diez", "once", "doce", "trece", "catorce",
        "quince", "dieciséis", "diecisiete", "dieciocho", "diecinueve",
        "veinte", "veintiuno", "veintidós", "veintitrés", "veinticuatro",
        "veinticinco", "veintiséis", "veintisiete", "veintiocho", "veintinueve"};
 
        private static String[] decenas={"","","","treinta", "cuarenta", "cincuenta",
            "sesenta", "setenta", "ochenta", "noventa"};
 
        private static String[] centenas ={"", "", "doscient", "trescient","cuatrocient",
            "quinient","seiscient","setecient","ochocient", "novecient"};
 
        private static String[] nombreMillonesSingular ={ "", "millón", "billón", "trillón", "cuatrillón" };
        private static String[] nombreMillonesPlural ={ "", "millones", "billones", "trillones", "cuatrillones" };
 
        private static String Convierte1(int i, Tipo t)
        {   
            String r;
            if ( (i==1) && (t==Tipo.DetMasculino))
            {
                r="un";
            }
            else if ( (i==1) && (t==Tipo.DetFemenino))
            {
                r="una";
            }
            else
            {
                r=nombresIrregulares[i];
            }
            return r;
        }//Convierte1
 
 
        private static String Convierte2(int i, Tipo t)
        {
            StringBuilder r=new StringBuilder();
            if (i <= 9)
            {
                r.Append(Convierte1(i,t));
            }
            else if (i==21 && t!=Tipo.Pronombre) 
            {
                if (t == Tipo.DetMasculino)
                {
                    r.Append("veintiún");
                }
                else 
                {
                    r.Append("veintiuna");
                }
            }
            else if (i >= 10 && i <= 29)
            {
                r.Append(nombresIrregulares[i]);
            }
            else
            {
                r.Append(decenas[i/10]);
                if (i % 10 != 0)
                {
                    r.Append(" y ");
                    r.Append(Convierte1(i%10, t));
                }
            }
            return r.ToString();
        }//Convierte2
 
        private static String Convierte3(int i, Tipo t) 
        {
            StringBuilder r=new StringBuilder();
            if (i <= 99)
            {
                r.Append(Convierte2(i, t));
            }
            else if (i == 100)
            {
                r.Append("cien");
            }
            else
            {
                if (i >= 101 && i <= 199)
                {
                    r.Append("ciento");
                }
                else
                {
                    r.Append(centenas[i / 100]);
                    r.Append(t == Tipo.DetFemenino ? "as" : "os");
                }
                if (i % 100 > 0)
                {
                    r.Append(" ");
                    r.Append(Convierte2(i % 100, t));
                }
            }
            return r.ToString();
        } //Convierte3
 
        private static String Convierte6(int i, Tipo t)
        {
            StringBuilder r=new StringBuilder();
            int tresPrimeros = i / 1000;
            int tresUltimos = i % 1000;
            if (tresPrimeros==1)
            {
                r.Append("mil");
            }
            else if (tresPrimeros >= 2)
            {
                if (t==Tipo.Pronombre)
                    r.Append(Convierte3(tresPrimeros, Tipo.DetMasculino));
                else
                    r.Append(Convierte3(tresPrimeros, t));
                r.Append(" mil");
            }
 
            if (tresUltimos > 0)
            {
                if (tresPrimeros > 0)
                {
                    r.Append(" ");
                }
                r.Append(Convierte3(tresUltimos,t));
            }
            return r.ToString();
        }
 
        private static bool EsNumero(String s)
        {
            bool resultado = true;
            int contador=0;
            int longitud=s.Length;
            while (resultado && contador<longitud)
            {
                if (s[contador] < '0' || s[contador] > '9')
                {
                    resultado = false;
                }
                contador++;
            }
            return resultado;
        }
 
        private static String ConvierteTodo(String s, Tipo t)
        {
            StringBuilder resultado=new StringBuilder();
            int cuenta = s.Length;
            int cuentamillones = 0;
            while (cuenta > 0)
            {
                int inicio = (cuenta - 6 >= 0) ? (cuenta - 6) : 0;
                int longitud = (6 > cuenta) ? cuenta : 6;
                String stemp = s.Substring(inicio, longitud);
                int i6 = int.Parse(stemp);
                if (cuentamillones > 0 && i6>0)
                {
                    if (resultado.Length > 0)
                    {
                        resultado.Insert(0, " ");
                    }
                    if (i6 > 1)
                    {
                        resultado.Insert(0, nombreMillonesPlural[cuentamillones]); 
                    }
                    else
                    {
                        resultado.Insert(0, nombreMillonesSingular[cuentamillones]);
                    }
                    resultado.Insert(0, " "); 
                }
                resultado.Insert(0, Convierte6(i6, t));
                if (cuentamillones == 0)
                {
                    t = Tipo.DetMasculino;
                }
                cuentamillones++;
                cuenta -= 6;
            };
            return resultado.ToString();
        }
        
        public static String Convierte(String s, Tipo t)
        {
            String resultado="";
            s = s.Trim();
            if (s.Length > 30)
            {
                resultado = "Demasiado grande. Llego hasta 30 cifras";
            }
            else if (!EsNumero(s))
            {
                resultado = "La cadena no está formada sólo por números";
            }
            else
            {
                resultado = ConvierteTodo(s, t);
            }
            return resultado;
        }
 
    }

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
 * Clase en Java para convertir números a su equivalente escrito.
 * Utilización: pásale al método público "Convierte" una cadena
 * de hasta 30 carácteres con la representación del número en cifras, y la
 * forma en la que debe actuar el número, como Pronombre, o como determinante
 * masculino o femenino, mediante un valor del enumerado Tipo, y te devolverá
 * una cadena con el número como texto.
 * 
 * Ejemplo:
 * System.out.println(NumLetrasJ.Convierte("12312343",NumLetrasJ.Tipo.Pronombre));
 * 
 * Puedes usar, modificar y distribuir libremente éste código, teniendo en cuenta
 * que se distribuye "tal cual", sin garantía ni responsabilidad de ningún tipo.
 * Si te resulta util, se agradece un link a "www.latecladeescape.com".
 * 
 * Éste código se acoge los términos de la licencia descrita a continuación en inglés
 * y su utilización de cualquier tipo supone la aceptación de dichos términos.
 * 
 * **************************************************************************
 * Copyright © 2007 by La tecla de ESCAPE <www.latecladeescape.com>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ****************************************************************************
 * @version 1.0
 * 
 */
public class NumLetrasJ {
 
        public enum Tipo {Pronombre, DetMasculino, DetFemenino};
 
        private static String[] nombresIrregulares ={
        "", "uno", "dos", "tres", "cuatro",
        "cinco", "seis", "siete", "ocho", "nueve",
        "diez", "once", "doce", "trece", "catorce",
        "quince", "dieciséis", "diecisiete", "dieciocho", "diecinueve",
        "veinte", "veintiuno", "veintidós", "veintitrés", "veinticuatro",
        "veinticinco", "veintiséis", "veintisiete", "veintiocho", "veintinueve"};
 
        private static String[] decenas={"","","","treinta", "cuarenta", "cincuenta",
            "sesenta", "setenta", "ochenta", "noventa"};
 
        private static String[] centenas ={"", "", "doscient", "trescient","cuatrocient",
            "quinient","seiscient","setecient","ochocient", "novecient"};
 
        private static String[] nombreMillonesSingular ={ "", "millón", "billón", "trillón", "cuatrillón" };
        private static String[] nombreMillonesPlural ={ "", "millones", "billones", "trillones", "cuatrillones" };
 
        private static String Convierte1(int i, Tipo t)
        {   
            String r;
            if ( (i==1) && (t==Tipo.DetMasculino))
            {
                r="un";
            }
            else if ( (i==1) && (t==Tipo.DetFemenino))
            {
                r="una";
            }
            else
            {
                r=nombresIrregulares[i];
            }
            return r;
        }//Convierte1
 
 
        private static String Convierte2(int i, Tipo t)
        {
            StringBuilder r=new StringBuilder();
            if (i <= 9)
            {
                r.append(Convierte1(i,t));
            }
            else if (i==21 && t!=Tipo.Pronombre) 
            {
                if (t == Tipo.DetMasculino)
                {
                    r.append("veintiún");
                }
                else 
                {
                    r.append("veintiuna");
                }
            }
            else if (i >= 10 && i <= 29)
            {
                r.append(nombresIrregulares[i]);
            }
            else
            {
                r.append(decenas[i/10]);
                if (i % 10 != 0)
                {
                    r.append(" y ");
                    r.append(Convierte1(i%10, t));
                }
            }
            return r.toString();
        }//Convierte2
 
        private static String Convierte3(int i, Tipo t) 
        {
            StringBuilder r=new StringBuilder();
            if (i <= 99)
            {
                r.append(Convierte2(i, t));
            }
            else if (i == 100)
            {
                r.append("cien");
            }
            else
            {
                if (i >= 101 && i <= 199)
                {
                    r.append("ciento");
                }
                else
                {
                    r.append(centenas[i / 100]);
                    r.append(t == Tipo.DetFemenino ? "as" : "os");
                }
                if (i % 100 > 0)
                {
                    r.append(" ");
                    r.append(Convierte2(i % 100, t));
                }
            }
            return r.toString();
        } //Convierte3
 
        private static String Convierte6(int i, Tipo t)
        {
            StringBuilder r=new StringBuilder();
            int tresPrimeros = i / 1000;
            int tresUltimos = i % 1000;
            if (tresPrimeros==1)
            {
                r.append("mil");
            }
            else if (tresPrimeros >= 2)
            {
                if (t==Tipo.Pronombre)
                    r.append(Convierte3(tresPrimeros, Tipo.DetMasculino));
                else
                    r.append(Convierte3(tresPrimeros, t));
                r.append(" mil");
            }
 
            if (tresUltimos > 0)
            {
                if (tresPrimeros > 0)
                {
                    r.append(" ");
                }
                r.append(Convierte3(tresUltimos,t));
            }
            return r.toString();
        }
 
        private static boolean EsNumero(String s)
        {
            boolean resultado = true;
            int contador=0;
            int longitud=s.length();
            while (resultado && contador<longitud)
            {
                if (s.charAt(contador) < '0' || s.charAt(contador) > '9')
                {
                    resultado = false;
                }
                contador++;
            }
            return resultado;
        }
 
        private static String ConvierteTodo(String s, Tipo t)
        {
            StringBuilder resultado=new StringBuilder();
            int cuenta = s.length();
            int cuentamillones = 0;
            while (cuenta > 0)
            {
                int inicio = (cuenta - 6 >= 0) ? (cuenta - 6) : 0;
                int longitud = (6 > cuenta) ? cuenta : 6;
                String stemp = s.substring(inicio, inicio+longitud);
                System.out.println(stemp);
                int i6 = Integer.parseInt(stemp);
                if (cuentamillones > 0 && i6>0)
                {
                    if (resultado.length() > 0)
                    {
                        resultado.insert(0, " ");
                    }
                    if (i6 > 1)
                    {
                        resultado.insert(0, nombreMillonesPlural[cuentamillones]); 
                    }
                    else
                    {
                        resultado.insert(0, nombreMillonesSingular[cuentamillones]);
                    }
                    resultado.insert(0, " "); 
                }
                resultado.insert(0, Convierte6(i6, t));
                if (cuentamillones == 0)
                {
                    t = Tipo.DetMasculino;
                }
                cuentamillones++;
                cuenta -= 6;
            };
            return resultado.toString();
        }
        
        public static String Convierte(String s, Tipo t)
        {
            String resultado="";
            s = s.trim();
            if (s.length() > 30)
            {
                resultado = "Demasiado grande. Llego hasta 30 cifras";
            }
            else if (!EsNumero(s))
            {
                resultado = "La cadena no está formada sólo por números";
            }
            else
            {
                resultado = ConvierteTodo(s, t);
            }
            return resultado;
        }
 
    }

Puedes descargar el código en C#, y si quieres una versión en Java, también. La versión en Java es prácticamente una traducción directa de la de C# (ojo al método substring de la clase string, que cambia de C# a Java).

Si quieres ver el código en acción, aquí tienes una mini-demo.

   

Síguenos  

   

¿Dónde estoy?  

Estás en La tecla de ESCAPE, un sitio web personal en el que nos gusta hablar de algoritmos, metodología de la programación, personajes de informática, tecnología, ingeniería del software, internet, y cualquier otra tontería que se nos ocurra.

[Leer más / Términos de uso (ToS)]

   

¿Quién está en línea?