Ir al contenido



Foto

Pasaje de números a letras

números letras conversión

  • Por favor identifícate para responder
44 respuestas en este tema

#21 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.106 mensajes
  • LocationMéxico

Escrito 07 julio 2015 - 08:37

Wow, muy interesante el reto, 34 lineas si que es muy poco código.

 

Saludos

 

Off-topic:    De todo el país, Zacatecas y Chihuahua son los únicos Estados que no conozco.


  • 0

#22 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 07 julio 2015 - 12:45

Que hay de nuevo colegas, aquí reportando unas optimizaciones que me tomé la molestia de realizar hoy a mi código,
después de optimizarlo eliminando variables y factorizando código pude bajar drásticamente la cantidad de lineas.
Creo que es necesario que establezcamos los lineamientos de la participación, por ejemplo si es necesario el salto de linea cada tantas columnas, y hasta que numero es necesario hacer la conversión.

 

por ahora mi código lo pude reducir a 34 lineas. Utilicé la función IfThen para emular el operador ternario de c++ y ahorrar 6 lineas de código, así como que estoy contando sentencias, es decir, no hago saltos de linea cada tantas columnas, además que el algoritmo sólo sigue traduciendo hasta un máximo de 999,999,999.99 y el formato de salida es en español de México.

 

Saludos desde un lugar en Zacatecas México...

 

Otra cosa la unidad ya terminada cuenta 58 lineas con saltos de linea y formateada correctamente con JediCodeFormat CTRL+D en lazarus, en este si se realizan saltos de linea para que haya lineas largas. además que como unidad ya posee sus secciones de interface, implementación, usos, etc.

Pero supongo que deberíamos contar solo las lineas efectivas, en mi caso 34 lineas desde la declaración de la función, su begin y end; ;)

 

Asombroso, realmente.

 

Lo que más me asombra es el alcance y que interpreta los decimales. :ap:  Que es como dice Escafandra, una vez que tengas el algoritmo principal los decimales se tratan de la misma manera.

 

Aun así, como dices, había impuesto unas restricciones para que el desafío sea parejo. Te las aclaro nuevamente, ya que las nombras:

1. Son todas las líneas desde unit hasta end. Pues no sería justo que yo descontara mis líneas de constantes, por ejemplo.

2. Las columnas llegan a un máximo de 100 caracteres.

3. los if, then y else van en diferentes líneas:


delphi
  1. if condición
  2. then sentencia1
  3. else sentencia2;
  4.  
  5. if condición1
  6. then sentencia1
  7. else if condición2
  8. then sentencia3
  9. else if ...

Pues de lo contrario pondríamos todo en una sola línea de if inicial y listo, tampoco sería justa una comparación con ideal buscado.

Esto se extiende a los bucles:


delphi
  1. repeat
  2. {...}
  3. until condición
  4.  
  5. while condición do
  6. begin
  7. {...}
  8. end;

4. Espacios entre las secciones, esto es obvio, son los espacios que genera el mismo IDE.

 

Y creo que esas eran todas.

 

En mi caso tengo cuatro declaraciones de constantes que usan dos líneas dada la limitación de los 100 caracteres. Esas son ocho líneas más, que junto al separador y la palabra reservada const hacen diez, que si no las contara sería un gran error. :wink:

 

Saludos


  • 0

#23 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.106 mensajes
  • LocationMéxico

Escrito 07 julio 2015 - 01:34

..... Lo que más me asombra es el alcance y que interpreta los decimales. :ap: Que es como dice Escafandra, una vez que tengas el algoritmo principal los decimales se tratan de la misma manera. .....

 

Tengo una duda

 

¿Como es que manejan ustedes los decimales?

 

Acá en México como ya he mencionado solo se colocan los centavos como fracción de 100 y las siglas de Moneda Nacional (25/100 M.N.)
 
Saludos


  • 0

#24 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 07 julio 2015 - 03:48

Tengo una duda

 

¿Como es que manejan ustedes los decimales?

 

Acá en México como ya he mencionado solo se colocan los centavos como fracción de 100 y las siglas de Moneda Nacional (25/100 M.N.)
 
Saludos

 

En Argentina, siempre en el ámbito comercial, se escribe algo parecido, es decir por ejemplo, para la cantidad 50,25$ que suelen escribir $50,25 (no sé por qué) será: "son pesos cincuenta con 25/100"

 

Saludos


Editado por cram, 07 julio 2015 - 03:50 .

  • 0

#25 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.106 mensajes
  • LocationMéxico

Escrito 07 julio 2015 - 04:31

En Argentina, siempre en el ámbito comercial, se escribe algo parecido, es decir por ejemplo, para la cantidad 50,25$ que suelen escribir $50,25 (no sé por qué) será: "son pesos cincuenta con 25/100"

 

Saludos

 

Que curioso, acá se escribiría así

 

Cincuenta Pesos 25/100 M.N.

 

La palabra "Son" no es usada en las facturas, a veces se usa en los cheques, cuando se hacen ya que no es tan común su uso en estos días de operaciones electrónicas.

 

Saludos


  • 0

#26 Dragonlair

Dragonlair

    Newbie

  • Miembros
  • Pip
  • 7 mensajes
  • LocationMéxico

Escrito 07 julio 2015 - 07:22

Ya lo acomodé a un máximo de 100 columnas, en ese caso creo quedará entonces en 54 caracteres y la verdad no creo poder bajar de ahí. Otra cosa que no tuve en cuenta y no se si ustedes consideraron es el tipo de dato de entrada, también el manejo de excepciones y valores negativos o ceros. En mi caso solo acepta tipos de datos ligados a valores currency o float en su defecto, y con el casting automático acepta enteros, aparte de no manejar excepciones, la entrada siempre debe ser un número mayor a cero no negativo.

Archivos adjuntos


  • 0

#27 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 08 julio 2015 - 07:17

Entonces hay dos claros vencedores del desafío, sin contarme, pues yo lo propuse.

Más allá que es aparentemente imbatible el tamaño de código de Dragonlair, discretamente es un triunfo.

El otro código sería el propuesto por Escafandra.

 

Yo también bajé los 100 con todas las reglas impuestas (por mí mismo, que en realidad tienen que ver con prácticas de escritura de código más o menos estándares).

 

Lo que no me queda claro es ¿qué es la emulación del ifthen? Conozco el iif y la forma de C, pero en Pascal, nunca lo usé.

 

¡DESAFÍO MACHACADO! (y)  <:o) 

 

Saludos


  • 0

#28 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.935 mensajes
  • LocationMadrid - España

Escrito 08 julio 2015 - 07:41

Bueno, yo tengo que buscar un rato para optimizar mi código. Lo que no tengo nada claro es que un código con menos líneas esté más optimizado. Trampas para bajar líneas hay muchas, otra cosa es como quede ese código compilado, habría que analizar el resultado en asm que es lo que va a presentar más o menos carga de trabajo al microprocesador y la velocidad de ejecución. En cualquier caso, el asunto de las 100 líneas es pan comido.

 

Sobre el asunto de decimales, en España escribimos el número hasta la coma, añadimos la palabra "con", y acto seguido tratamos la parte decimal como la parte entera, tenga los decimales que tenga.

 

 

Saludos.


  • 0

#29 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 08 julio 2015 - 09:37

Bueno, yo tengo que buscar un rato para optimizar mi código. Lo que no tengo nada claro es que un código con menos líneas esté más optimizado. Trampas para bajar líneas hay muchas, otra cosa es como quede ese código compilado, habría que analizar el resultado en asm que es lo que va a presentar más o menos carga de trabajo al microprocesador y la velocidad de ejecución. En cualquier caso, el asunto de las 100 líneas es pan comido.

 

Sobre el asunto de decimales, en España escribimos el número hasta la coma, añadimos la palabra "con", y acto seguido tratamos la parte decimal como la parte entera, tenga los decimales que tenga.

 

 

Saludos.

 

Más claro imposible y comparto tu opinión (y)  . En realidad es un desafío algo flaco.

Por ejemplo el uso de case y sets hace un código menos eficiente. Aun así, el desafío era ese, nada muy serio.

 

Por eso hice hincapié en el tema de las columnas de caracteres y los saltos de párrafos.

Por otra parte se supone que había que pasar un número entero, ¿no se de donde salió el tema de moneda? el asunto es que una vez hecho el algoritmo principal, se puede separar al número usando la coma, o agregarle leyendas como más y menos, porciento, pesos, etc. Pero ese no era el reto.

 

Aquí dejo mi código (nublado) quizás después lo ponga completo para compartirlo (qué más dá) y un ejemplo.

Función sobrecargada aceptando string o integer, para el caso de strings tiene una capacidad de 57 caracteres, es decir nonillones.

Alcanza las 76 líneas, que en realidad son 75 (un error en const de dos líneas sin necesidad).

 

Archivo adjunto  cod_NumLetras.jpg   15,7KB   1 descargas

 

Saludos

Archivos adjuntos


  • 1

#30 Dragonlair

Dragonlair

    Newbie

  • Miembros
  • Pip
  • 7 mensajes
  • LocationMéxico

Escrito 08 julio 2015 - 10:42

el equivalente del operador ternario de c++


delphi
  1. if trunc(Value) > 1000000 then
  2. Result += ' MILLONES'
  3. else
  4. Result += ' MILLON';
  5.  
  6. Result += IfThen(trunc(Value) > 1000000, ' MILLONES', ' MILLON');


  • 1

#31 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 08 julio 2015 - 11:25

 

el equivalente del operador ternario de c++


delphi
  1. if trunc(Value) > 1000000 then
  2. Result += ' MILLONES'
  3. else
  4. Result += ' MILLON';
  5.  
  6. Result += IfThen(trunc(Value) > 1000000, ' MILLONES', ' MILLON');

 

Ahora entiendo, no lo conocía.

Cómodo en ciertos casos, pero solo es de FreePascal, no de ObjectPascal, por lo que veo.

Es una función de StrUtils y solo funciona para el tratamiento de cadenas de caracteres. ¡Si se pudiera anidar!


php
  1. m:= ifthen (c<>1, 'a', 'b');  //m es de tipo string

si c= 1 entonces m valdrá 'b', caso contrario m valdrá 'a'

 

Pasa que soy algo novato en FreePascal.

 

Solo por curiosidad, ¿pasarías tu código a ObjectPascal?, y nos cuentas los resultados. :wink:

Saludos


  • 1

#32 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.935 mensajes
  • LocationMadrid - España

Escrito 09 julio 2015 - 02:26

He trabajado un poco más en mi código, aunque quizás se pueda optimizar un poco más en cuanto al número de líneas. Los resultados son estos:
1.- Abarca hasta un cuatrillón tipo 1E24, es decir cuatrillón español, y supongo que de todos los hispanoparlantes.
2.- No implementé decimales, dado que cram no lo incluyó en las bases.
3.- Lo he implementado en una unit a parte como estableció cram  y abarca tras el formateo "oficial" 65 líneas y podría recortar otras 4.
4.- He usado delphi puro y duro, sin similitudes de compilación tipo C, lenguaje "experto" en recortar código.
5.- Si lo recorto a 999.9999.9999 entonces abarca 8 líneas menos, es decir, 57 líneas.
 
He usado trucos como sustiuir condicionales por operaciones lógicas y binarias en la misma expresión para calcular índices, esto ofusca bastante el código pero probablemente no le reste eficiencia para el micro.
Una muestra sería esto:


cpp
  1. Result:=dec[ord(N[i])-48]+suf[WORD((N[i]='2')and(N[i-1]>'0'))+2*WORD(N[i]>'2')+WORD((N[i]>'2')and(N[i-1]='0'))]+Result;

También he usado recursividad pasando como parámetro trozos del número a calcular, es por eso que llegar al cuatrillón me consume 8 líneas.
 
Como dijo cram, a mí tampoco me importará publicar el código. :)
 
 
Saludos.

Archivos adjuntos


  • 2

#33 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.935 mensajes
  • LocationMadrid - España

Escrito 10 julio 2015 - 06:26

Lo dicho, 4 líneas menos.

Unit escrita en delphi (ObjectPascal) que abarca hasta el cuatrillón (1E24) y ocupa 61 líneas.


Saludos.
  • 1

#34 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.106 mensajes
  • LocationMéxico

Escrito 10 julio 2015 - 08:11

Muy interesante el reto, ya llegó a 61 lineas :)

 

Saludos


  • 0

#35 Dragonlair

Dragonlair

    Newbie

  • Miembros
  • Pip
  • 7 mensajes
  • LocationMéxico

Escrito 10 julio 2015 - 12:16

El código está en objectpascal, así me lo marca el IDE, tendría que escribirlo en delphi para poder ver que funciones que utilizo no están dentro de las librerías de delphi. Desafortunadamente no poseo una licencia de delphi para hacer la conversión.

A lo que alcanzo a apreciar en la funcion de scafandra puede que su código sea mas eficiente ya que el trabaja el valor ingresado como una cadena y al parecer trabaja con las posiciones de los caracteres para su representación literal, quizá mi código se salió de lo propuesto ya que ciertamente no se pedia la representación literal con decimales y mi participación los incluyó a raíz del uso para expedir notas de venta o facturas, de todos modos creo que cumplimos con el objetivo de competir con un código que no utilizara fuerza bruta. saludos y he aquí mi aporte a la comunidad.


delphi
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8. SysUtils, strutils; //SysUtils necesario para la funcion trim(), strutils necesario para la funcion ifthen(,,)
  9.  
  10. function ValueToLetter(Value: currency): string;
  11.  
  12. implementation
  13.  
  14. function ValueToLetter(Value: currency): string;
  15. const // :)
  16. sUnits: array[0..15] of string = ('', 'UN', 'DOS', 'TRES', 'CUATRO', 'CINCO',
  17. 'SEIS', 'SIETE', 'OCHO', 'NUEVE', 'DIEZ', 'ONCE', 'DOCE', 'TRECE', 'CATORCE', 'QUINCE');
  18. sTens: array[0..9] of string = ('', 'DIECI', 'VEINTI', 'TREINTA', 'CUARENTA',
  19. 'CINCUENTA', 'SESENTA', 'SETENTA', 'OCHENTA', 'NOVENTA');
  20. sHundreds: array[0..9] of string = ('', 'CIEN', 'DOSCIENTOS', 'TRESCIENTOS',
  21. 'CUATROCIENTOS', 'QUINIENTOS', 'SEISCIENTOS', 'SETECIENTOS', 'OCHOCIENTOS', 'NOVECIENTOS');
  22. Op: array[0..2] of integer = (1, 1000, 1000000);
  23. var
  24. iTemp, i: Integer; //itemp contendrá una representacion entera de un número base 100 para su posterior tratamiento
  25. cTemp: Currency; //para contener temporalmente al numero en operacion y mantener el valor original contenido en Value
  26. begin
  27. cTemp := Value;
  28. for i := 2 downto 0 do // el número ingresado siempre se tratará en parejas de 3, ejemplo 487562784.65, la primera parte que se tratará es 487.
  29. begin
  30. iTemp := trunc(cTemp / Op[i]); //para extraer la pareja de tres números dividimos, 487562784.65 / 1000000 = 487.56278465, truncamos 487.
  31. cTemp -= iTemp * Op[i]; //extraemos esa parte del número en operacion 487562784.65 - 487*1000000 = 562784.65
  32. if (i > 0) and (iTemp < 1) then //si el resultado de la separación de la pareja es 0 y todavía no es la última iteracion entonces saltamos a la siguiente iteración, al no haber operaciones que realizar
  33. Continue;
  34. Result += ' ' + sHundreds[iTemp div 100]; // traducimos las centenas a su representacion literal correspondiente, simplemente extraemos el número correspondiente haciendo una division entera del número a 100
  35. iTemp -= iTemp div 100 * 100; //restamos las centenas del número que estamos tratando
  36. case iTemp of //utilizando este case podemos tratar la última parte del número, decenas y unidades
  37. 0..15: Result += ' ' + sUnits[iTemp];
  38. 16..19, 21..29: Result += ' ' + sTens[iTemp div 10] + sUnits[iTemp mod 10];
  39. 20: Result += ' VEINTE';
  40. 30, 40, 50, 60, 70, 80, 90: Result += sTens[iTemp div 10];
  41. 31..39, 41..49, 51..59, 61..69, 71..79, 81..89, 91..99: Result +=
  42. ' ' + sTens[iTemp div 10] + ' Y ' + sUnits[iTemp mod 10];
  43. end;
  44. case i of // dada la parte que estemos tratando agregamos el sufijo correspondiente
  45. 2: Result += IfThen(trunc(Value) > 1999999, ' MILLONES', ' MILLON');
  46. 1: Result += IfThen(trunc(Value) mod 1000000) > 999, ' MIL');
  47. end;
  48. Result := Trim(Result);
  49. end;
  50. Result += ifthen(value = 0, 'CERO') + IfThen(trunc(Value) = 1, ' PESO', ' PESOS') +
  51. Format(' %.2d/100 M.N.', [trunc(cTemp * 100)]); //como al final substraimos toda la parte entera del valor original entonces sólo multiplicamos por 100 y truncamos para obtener la representación entera de los decimales
  52. end;
  53.  
  54. end.

Repito que es muy probable que requiera cambios menores para su empleo en delphi pero andamos en el mismo barco "pascal".

Además reitero que tomé la lógica de las substracciones de los números de la función IntToRoman contenida en la librería strutils perteneciente a la RunTimeLibrary de freepascal.

Saludos a todos.


  • 2

#36 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.935 mensajes
  • LocationMadrid - España

Escrito 10 julio 2015 - 01:30

El código está en objectpascal, así me lo marca el IDE...

Si lo escribiste con Lazarus, en las opciones de compilación tienes esa configuración estilo "C".
post-12294-0-68771700-1436556747.jpg
 

A lo que alcanzo a apreciar en la funcion de scafandra puede que su código sea mas eficiente ya que el trabaja el valor ingresado como una cadena y al parecer trabaja con las posiciones de los caracteres para su representación literal...

Estás en lo cierto, trabajo analizando los caracteres numéricos uno a uno y recursivamente en grupos.

Este es el código:

delphi
  1. unit Literales;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, SysUtils, StrUtils;
  7.  
  8. function ToLiteral(N: String): String;
  9.  
  10. implementation
  11.  
  12. function ToLiteral(N: String): String;
  13. function Numeros(N: String): String;
  14. const
  15. suf: array[0..7]of string=('e','i','ta y ','ta','','to ','ientos ','ientos ');
  16. uni: array[0..19]of string=('','uno','dos','tres','cuatro','cinco','seis','siete','ocho','nueve',
  17. 'diez','once','doce','trece','catorce','quince','dieciseis','diecisite','dieciocho','diecinueve');
  18. dec: array[2..9]of string=('veint','trein','cuaren','cincuen','sesen','seten','ochen','noven');
  19. cen: array[1..9]of string=('cien','dosc','tresc','cuatroc','quin','seisc','setec','ochoc','noevec');
  20. var
  21. tm: String;
  22. i: integer;
  23. begin
  24. for i:= 1 to Length(N) do
  25. begin
  26. tm:= Numeros(copy(N, i, 3*WORD((i>3)and(i<5))+6*WORD(i>6))); // se copian 0, 3 ó 6 caracteres
  27. if i = 1 then // Unidades
  28. Result:= uni[ord(N[i])-48]
  29. else if (i = 2) and (N[i] = '1') then // Decenas
  30. Result:= uni[ord(N[1])-38]
  31. else if (i = 2) and (N[i] > '1') then
  32. Result:=dec[ord(N[i])-48]+suf[WORD((N[i]='2')and(N[i-1]>'0'))+2*WORD(N[i]>'2')+WORD((N[i]>'2')
  33. and(N[i-1]='0'))]+Result
  34. else if (i = 3) and(N[i] >= '1')then // Centenas
  35. Result:= cen[ord(N[i])-48]+suf[3+WORD(N[i]='1')+WORD((N[i]='1')and(N[i-1]>'0')or(N[i-2]>'0'))+
  36. 3*WORD(N[i]>'1')]+Result
  37. else if (i = 4) and (tm = 'uno') then // Millares
  38. Result:= 'mil ' + Result
  39. else if (i = 4) and (tm <> '') then
  40. Result:= tm + ' mil ' + Result
  41. else if (i = 7) and (N[i] = '1') then //Millones
  42. Result:= 'un millón ' + Result
  43. else if (i = 7) and (tm <> '') then
  44. Result:= tm + ' millones ' + Result
  45. else if (i = 13) and (N[i] = '1') then //Billones
  46. Result:= 'un billón ' + Result
  47. else if (i = 13) and (tm <> '') then
  48. Result:= tm + ' billones ' + Result
  49. else if (i = 19) and (N[i] = '1') then //Trillones
  50. Result:= 'un trillón ' + Result
  51. else if (i = 19) and (tm <> '') then
  52. Result:= tm + ' trillones ' + Result;
  53. end;
  54. Result:= Trim(Result);
  55. end;
  56. begin
  57. Result:= Numeros(ReverseString(N));
  58. if Result = '' then Result:= 'cero';
  59. end;
  60.  
  61. end.

Saludos.

Archivos adjuntos


  • 1

#37 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.106 mensajes
  • LocationMéxico

Escrito 10 julio 2015 - 01:39

Hola

 

Muy interesante la forma como analizas los números amigo escafandra. (y)

 

Saludos


  • 0

#38 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.935 mensajes
  • LocationMadrid - España

Escrito 10 julio 2015 - 01:50

Muy interesante la forma como analizas los números amigo escafandra. (y)


Bueno, los analizo copiando como lo hace más o menos la mente humana. Si lo pensamos, miramos grupos de caracteres y realizamos recursividad en su análisis. La diferencia es que lo hago de derecha a izquierda, mientras que los humanos lo hacemos de izquierda a derecha.

El código tiene partes difíciles de entender, pero se trataba de compactar y con ello, a veces, no queda mas remedio que usar trucos que ofuscan. Al sustituir sentencias if por operaciones lógicas que mezclan con la lógica de expresiones con la aritmética y lógica binaria. El código original era más asequible aunque un poco, no mucho, más largo.


Saludos.
  • 2

#39 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 10 julio 2015 - 07:51

Me resta entonces agregar mi código.

Quiero aclararles que puedo eliminar la inclusión de la biblioteca SysUtils usando unos trucos con los ASCIIs. Pero lo prefiero así:

La variante que acepta un entero como parámetro de entrada solo puede procesaro hasta el máximo que acepte un entero, pero se supone que el número será pasado como cadena de caracteres y es aquí, donde el algoritmo permite interpretar hasta 57 cifras (nonillones).

Separa de a tres la cadena agregando uno o dos ceros al principio en caso que la longitud no sea múltiplo de tres (esto ahorra proceso).

Identifica la posición de los grupos de tres y agrega los sufijos mil o millón (millones) según el caso.

Identifica el caso de tener que escribir un o uno.

Lo más básico es que los nombres que hay que armar son en realidad los que forman las tres cifras, lo demás son sufijos.


php
  1. unit NumLetras;
  2.  
  3. interface
  4.  
  5. uses
  6.   System.SysUtils;
  7.  
  8. function NumALetras(S: String): String; Overload;
  9. function NumALetras(N: Integer): String; Overload;
  10.  
  11. implementation
  12.  
  13. const
  14.   C: array[0..9] of String = ('', 'cien', 'doscientos', 'trescientos', 'cuatrocientos', 'quinientos',
  15.     'seiscientos', 'setecientos', 'ochocientos', 'novecientos');
  16.   D: array[0..9] of String = ('', '', 'veinte', 'treinta', 'cuarenta', 'cincuenta', 'sesenta', 'setenta',
  17.     'ochenta', 'noventa');
  18.   U: array[0..9] of String = ('', 'un', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho',
  19.     'nueve');
  20.   D1: array[0..9] of String = ('diez', 'once', 'doce', 'trece', 'catorce', 'quince', 'dieciseis',
  21.     'diecisiete', 'dieciocho', 'diecinueve');
  22.   M: array[0..9] of String = ('', ' mill', ' bill', ' trill', ' cuatrill', ' quintill', ' sextill',
  23.     ' septill', ' octill', ' nonill');
  24.  
  25. function NumALetras(N: Integer): String;
  26. begin
  27.   Result:= NumALetras(IntToStr(N));
  28.  
  29. function NumALetras(S: String): String;
  30. var
  31.   P, I, zU, zD, zC: Integer;
  32.   R, L: String;
  33. begin
  34.   L:= '';
  35.   P:= 0;
  36.   if Length(S) mod 3 = 1
  37.     then S:= '00' + S
  38.     else if Length(S) mod 3 = 2
  39.       then S:= '0' + S;
  40.   I:= Length(S);
  41.   while I > 0 do
  42.   begin
  43.     TryStrToInt(S[I], zU);
  44.     TryStrToInt(S[I-1], zD);
  45.     TryStrToInt(S[I-2], zC);
  46.     R:= '';
  47.     if zC <> 1
  48.       then R:= C[zC]
  49.       else if zU + zD > 0
  50.         then R:= 'ciento'
  51.         else R:= C[zC];
  52.     if zD = 1
  53.       then R:= R + ' ' + D1[zU]
  54.       else if zU = 0
  55.       then R:= R + ' ' + D[zD]
  56.         else if zD = 2
  57.           then R:= R + ' ' + 'veinti' + U[zU]
  58.           else if zD = 0
  59.             then R:= R + ' ' + D[zD] + U[zU]
  60.             else R:= R + ' ' + D[zD] + ' y ' + U[zU];
  61.     if (P = 0) and (zU = 1)
  62.       then R:= R + 'o';
  63.     if Odd(P) and (zU + zD + zC > 0) then R:= R + ' mil ';
  64.     if not Odd(P) and (P > 1)
  65.       then if (zU = 1) and (zD + zC = 0)
  66.         then R:= R + M[P div 2] + 'ón '
  67.         else R:= R + M[P div 2] + 'ones ';
  68.     L:= R + L;
  69.     I:= I - 3;
  70.     P:= P + 1;
  71.   end;
  72.   Result:= L;
  73.  

Ah!... no interpreta el cero, pero es fácil de arreglar. El asunto es que no me interesa que lo procese, ya que puedo hacerlo fuera de la rutina.


  • 0

#40 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 10 julio 2015 - 07:56

Y así quedaría como lo tengo para usar:

 



php
  1. unit NumLetras;
  2.  
  3. interface
  4.  
  5. uses
  6.   System.SysUtils;
  7.  
  8. function NumALetras(S: String): String; Overload;
  9. function NumALetras(N: Integer): String; Overload;
  10.  
  11. implementation
  12.  
  13. const
  14.   C: array[0..9] of String = ('', 'cien', 'doscientos', 'trescientos', 'cuatrocientos', 'quinientos',
  15.     'seiscientos', 'setecientos', 'ochocientos', 'novecientos');
  16.   D: array[0..9] of String = ('', '', 'veinte', 'treinta', 'cuarenta', 'cincuenta', 'sesenta', 'setenta',
  17.     'ochenta', 'noventa');
  18.   U: array[0..9] of String = ('', 'un', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve');
  19.   D1: array[0..9] of String = ('diez', 'once', 'doce', 'trece', 'catorce', 'quince', 'dieciseis',
  20.     'diecisiete', 'dieciocho', 'diecinueve');
  21.   M: array[0..9] of String = ('', ' mill', ' bill', ' trill', ' cuatrill', ' quintill', ' sextill',
  22.     ' septill', ' octill', ' nonill');
  23.  
  24. function NumALetras(N: Integer): String;
  25. begin
  26.   Result:= NumALetras(IntToStr(N));
  27.  
  28. function NumALetras(S: String): String;
  29. var
  30.   P, I, zU, zD, zC: Integer;
  31.   R, L: String;
  32. begin
  33.   L:= '';
  34.   P:= 0;
  35.   if Length(S) mod 3 = 1 then S:= '00' + S
  36. else if Length(S) mod 3 = 2 then S:= '0' + S;
  37.   I:= Length(S);
  38.   while I > 0 do
  39.   begin
  40.     TryStrToInt(S[I], zU);
  41.     TryStrToInt(S[I-1], zD);
  42.     TryStrToInt(S[I-2], zC);
  43.     R:= '';
  44.     if zC <> 1 then R:= C[zC] else if zU + zD > 0 then R:= 'ciento' else R:= C[zC];
  45.     if zD = 1 then R:= R + ' ' + D1[zU]
  46. else if zU = 0 then R:= R + ' ' + D[zD]
  47. else if zD = 2 then R:= R + ' ' + 'veinti' + U[zU]
  48.           else if zD = 0 then R:= R + ' ' + D[zD] + U[zU]
  49.             else R:= R + ' ' + D[zD] + ' y ' + U[zU];
  50.     if (P = 0) and (zU = 1) then R:= R + 'o';
  51.     if Odd(P) and (zU + zD + zC > 0) then R:= R + ' mil ';
  52.     if not Odd(P) and (P > 1) then if (zU = 1) and (zD + zC = 0) then R:= R + M[P div 2] + 'ón '
  53.         else R:= R + M[P div 2] + 'ones ';
  54.     L:= R + L;
  55.     I:= I - 3;
  56.     P:= P + 1;
  57.   end;
  58.   Result:= L;
  59.  


  • 2