domingo, 24 de febrero de 2013


vi = valor inicial.
cdu = ( unidad, decena, centena ). 
Number = Cadena de entrada ( contiene el numero que se va a leer )
l = longitud de la cadena de entrada 
i = posicion de cada digito comenzando desde la ultima posicion.   vi: l
d = digito ( cada uno de los digitos que se leen de la entrada ). 
u = undad.       vi : u = 1      u = u * 10,   ( unidad = 1, decena = 10 centena = 100 )  
v = vector ( almacena las cadenas de lectura ).     Unidad: V[ n ]          Decena: V[ 20 + p ] exceptuando [ 10 - 19 ] = V[ n ]                Centena: V[ 30 + p ]                                   Miles/millones/billones = V[ 40 + p ]
n = valor acumulativo cdu.      vi : n = 0       n = d * u + n
s = buffer auxiliar ( almacena la concatenacion de  cdu ).   s = c + d + u
z = buffer principal.  ( contiene la cadena completa de salida ).   z  = cdu + cdu + cdu ...
p = posicion ( calcula la posicion en el vector de cadenas de lectura )   vi: p = 0    decena: p = d - 2  centena: p = d - 1  Miles/Millones: p = {  miles = 0, millones = 1, billones = 2  }
=  cadena temporal.
j = contador de milesimas/millones/billones. vi: 0   Ejs: 123.873.984.930 :  j = 3,     1.983 :  j = 1
r = diferencia entre la longitud y la posicion del digito.     r = l - i 
----------------------------------------------------------------------------------------------------------------------





La lógica del algoritmo es empezar leyendo carácter a carácter de derecha a izquierda (cadena inversa), cada 3 dígitos almacenamos el buffer auxiliar  en el buffer principal, luego reiniciamos el buffer auxiliar y las operaciones (se reinicia todo excepto el buffer principal y contador de miles/millones/billones).


U: valor de la unidad, inicia en 1,    U =  U * 10 , { U = 1 = Unidad, U =10=Decena,  U=100=Centena}
Reiniciamos por cada 3 dígitos que se lean (CDU = Centena.Decena. Unidad)
Ej: leemos 7254
it 1: U = 1
it 2: U = 10
it 3: U = 100
Reiniciamos U = 1
it 4: U = 1
….
n: valor acumulativo, inicia en 0,   n = d * u + n  
Reiniciamos n  = 0 por cada 3 dígitos que se lean (CDU)
Ej: leemos 7254
it 1: [  d = 4, U = 1, n = 0  ] entonces  n = ( 4 * 1 + 0 )  =  4
it 2: [  d = 5, U = 10, n = 4  ] entonces  n = (5 * 10 + 4)  = 54
it 3: [  d = 2, U = 100, n = 54  ] entonces  n =( 2 * 100 + 54 )  = 254
Reiniciamos  n = 0
it 4: [  d = 7, U = 1, n = 0  ] entonces  n =( 7 * 1 + 0 )  = 7
Tomemos los valores de n  y u de arriba para cada iteración.
Unidades: posiciones en el vector [0 – 9] entonces  se accede de forma directa   V[n]
Ej: leemos 7254
it 1: [  d = 4, U = 1, n = 4  ] , V[4] = “cuatro”
it 2: …entra en decena
it 3: …entra en centena
Reiniciamos  n = 0, U = 1
it 4: [  d = 7, U = 1, n = 7 ],  V[7] = “siete”
Decenas: posiciones en el vector [20 – 27], entonces V [20 + p],  donde p = d – 2, si p < 0 entonces está en el rango     [10 - 19]  su valor se obtiene con V[n]  
Ej: leemos 7254
it 1: …entra en unidad
it 2: [  d = 5, U = 10, n = 54 ] entonces, p = ( 5 - 2) = 3,   V[23] = “cincuenta”,
Si el digito leído fuera 1 en lugar de 5, es decir fuera 7214,  entonces n = 14,  p = (1 - 2) = (-1)  < 0,  por tanto obtendríamos su valor directo con V [14] =”catorce” limpiaríamos el valor de la unidad que era “cuatro”.
it 3: …entra en centena
Reiniciamos  n = 0, U = 1
it 4: …entra en unidad
Centenas: posiciones en el vector [30 – 38], entonces V [30 + p],  donde p = d – 1
Ej: leemos 7254
it 1: …entra en unidad
it 2: …entra en decena
it 3: [  d = 2, U = 100, n = 254 ], p = (2 - 1) = 1,  V[31] = “doscientos”
Reiniciamos  n = 0, U = 1
it 4: …entra en unidad

Miles/millones/billones: V [40 + p], donde p = {0, 1 o 2},  si ( j > 2 ) entonces p = 2 sino p = j & 1,   r = l - i
( J & 1 ) devuelve 0 si j es par y 1 si es impar, ( 0  & 1) = 0,  (1 & 1) = 1, (2 & 1) = 0, (3 & 1) = 0 …
r es la diferencia entre l (longitud total de la cadena numérica de entrada ) e  i( índice del digito leído )
j es un valor  que inicia en 0 y  se incrementa siempre que encuentre una unidad Miles/millones/billones
Solo se calcula Miles/millones/billones si  r  > 0, verifica que hayan dígitos por leer  y si  r mod  3 = 0, es decir si se ha leído una (CDU), entonces si ambas condiciones se cumplen calculamos p  y  buscamos en el vector.
Ej: leemos 7254
it 1: [ j = 0, l = 4, i = 4 ] …entra en unidad  r = ( 4 – 4 ) =  0, verificamos  ( 0  > 0 ) No, ( 0 mod  3 = 0 )  Si
it 2: [ j = 0, l = 4, i = 3 ] …entra en decena r = ( 4 – 3 ) =  1, verificamos  ( 1  > 0 ) Si, ( 1 mod  3 = 0 )  No
it 3: [ j = 0, l = 4, i = 2] …entra en centena r = ( 4 – 2 ) =  2, verificamos  ( 2  > 0 ) Si, ( 2 mod  3 = 0 )  No
Reiniciamos  n = 0, U = 1
it 4: [ j = 0, l = 4, i = 1] …entra en unidad  r = ( 4 – 1 ) =  3, verificamos  ( 3  > 0 ) Si, ( 3 mod  3 = 0 )  Si
Se cumplen ambas condiciones entonces calculamos p, si  ( j = 0) > 2 No  entonces p = ( 0 & 1 ) = 0,
V[40  + 0 ] = “mil”


 Ej: para 2258, l = 4, entonces, iteración 1:  [i = 4, d = 8, u = 1, n = 0],  n = ( 8 * 1 + 0 ) = 8 , si u = 1, entonces accedemos a su valor en el vector directamente v [ n ], el valor será s = v[ 8 ] = "ocho", entonces n = 8, u = 10, s ="ocho", iteración 2:  [i = 3, d = 5, u = 10, n = 8],        n  = ( 5 * 10  + 8 ) = 58, si u = 10, entonces p = d – 2  es decir p = ( 5 – 2 ) = 3,  si p >= 0 y d <> 2 entonces  t = v[ 20 + p ] , t = V[ 23 ] = “cincuenta”, entonces n = 58, u = 100, s = (  t + “ y ” + s ) = “cincuenta y ocho”, si d = 2 si en el ejemplo fuera 1228 entonces seria , n = ( 2 * 10 + 8 ) = 28, p = ( 2 – 2 ) = 0,  t = v[ 20 ] = “veinte”,  s = ( “veinti” + s ) = “veintiocho” para esta iteración,   si p < 0 quiere decir que la unidad de decena esta entre [ 10 – 19 ] por lo cual accedemos directamente  v[ n ] , si en el ejemplo fuera 1218 entonces  en esta iteración el valor acumulativo seria n = ( 1 * 10 + 8 ) = 18 , p = ( 1 – 2 ) = (-1), por tanto obtendríamos t = v[ 18 ] = “dieciocho”, iteración 3: [i = 2, d = 2, u = 100, n = 58],  n = ( 2 * 100 + 58 ) = 258, si u = 100, entonces p = d – 1  es decir p = ( 2 – 1 ) = 1,  si d <> 1, entonces  t = v[ 30 + p ] , t = v[ 31 ] = “doscientos”, s = ( t + “ “ + s )  = “doscientos cincuenta y ocho”, si d = 1 si en el ejemplo fuera 1128 entonces seria  entonces p = ( 1 – 1 ) = 0,  t = v[ 30 + p ] + “to”,  t = ( v[30] + “to” ) =”ciento”, s = ( t + s ) = “ciento cincuenta y ocho”, como u  = 100 entonces reiniciamos todas las variables pero antes guardamos en el buffer principal (z) el buffer auxiliar = cdu (s), es decir z = s = “ciento cincuenta y ocho”, reiniciamos variables u = 1, s = ””, n = 0, repetimos los pasos anteriores iteración 4: [i = 1, d = 2, u = 1, n = 0] , aquí hacemos lo mismo que en la iteración 1,  n = ( 2 * 1 + 0 )  = 2 , si u = 1, si u = 1, entonces accedemos a su valor en el vector directamente v [ n ], el valor será s = v[ 2 ] = "dos", como hemos terminado de leer los caracteres terminamos las iteraciones.Este paso se hace en cada iteración, verifica los miles/millones/billones
j es un contador miles/millones/billones que inicia en 0 e incrementa siempre que  encuentra una unidad  de miles/millones/billones.
l es longitud de vector
i es el índice de posiciones de cada digito

1.    obtener la posición real,  r = l – i
2.    Verificar si hay más números por leer esto se verifica, r  >  0
3.    verificar  si es es miles/millones/billones,  r  mod  3 = 0
4.    si 2 y 3 se cumplen, calcular posición del vector, entonces
p = ( r > 10 ) ?  2 : j++ & 1;  
explico esta instrucción:

si r > 10, p = 2 es decir que son billones, si no es asi hago un and  a nivel de bits sobre j, este and (& ) lo que me devuelve es 0 si es par y 1 si es impar, Ej:
p = j & 1
para j = 0 :  p = ( 0 & 1 ) = 0 , j = 1 : p= (1 & 1) = 1 , j =2 :   p ( 2 & 1 ) = 0 …
5.    t = V[ 40 + p ]

para el ejemplo actual 2258, solo se cumplen las 2 condiciones en la iteracion 4: como i empieza en l, entonces parar it 1: i  = 4, it 2: i  = 3, it 3: i  = 2, it 4: i  = 1
iteracion 4: [l = 4, i = 0, j = 0, r  =  l – i ], entonces  r = ( 4  - 1 ) = 3,
r > 0  = si , r mod 3 = 0  = si, se cumplen ambas entonces,  r > 10 no cumple por tanto p = j++ & 1,  p = ( 0 & 1 ) = 0 , incrementa  j = 1, accedemos a vector t = v[40 + p], t = v[40] = “mil”, z = ( “ ” + t + “ ” + z )  = “ mil doscientos cincuenta y ocho”


Al salir del ciclo
Z =  ( s + z ) , como z = “ mil doscientos cincuenta y ocho” y s = “dos”, entonces z = “dos mil doscientos cincuenta y ocho”

sábado, 23 de febrero de 2013

Algoritmos Java y VB 6.0

este algorimo, es desarrollado por mi, es muy optimo y rapido no usa recursividad ni uso de substrings excesivos, ni tampoco divisiones concurrentes, se puede acceder casi directo a las cadenas de lectura, solo calculando la posicion con simples operaciones aritmeticas, copiar y pegar en una clase. y llamar al metodo desde el main abajo anexo la explicacion del algoritmo y los links de los codigos fuentes.

Ej: (clase).readNumber( "28377273.83", ".", "pesos" )
salida>>  veintiocho millones trescientos setenta y siete mil doscientos setenta y tres pesos con 83 centavos

private static final int  Unidad = 1; 
private static final int  Decena = 10;
private static final int  Centena = 100;

public static String readNumber( String Number, String sepDecimal, String sMoney ){
      
      String  V[] = initVector(), s = "", z = "", c = "", e = " ", t;
      int l = Number.length(), k = Number.indexOf( sepDecimal ), u = 1, n = 0, j = 0, b = 0, d, p, r;
     
      try{

           //obtiene los decimales
            if( k >= 0 ) { c = Number.substring( k + 1, l );  l = k; }
           
            if ( l <= 15 )
            {
                        for( int i = l ; i >= 1; i-- ){
                            d = Integer.parseInt( String.valueOf( Number.charAt( i - 1 ) ));
                            n = ( d * u ) + n;

                                switch( u ){
                                    case Unidad:
                                        s = V[ n ];
                                        if ( i == l && n == 1 ) b++;
                                    break;
                     case Decena:                                               
                                        p = d - 2;
                                   
                                        if( p < 0 )  
                                            s = V[ n ];                                     
                                        else{
                                            t =  V[ 20 + p ];
                                           
                                            if( n % 10 != 0 )
                                               s  =  (d == 2)? "veinti" + s : t + " y " + s;
                                            else   
                                               s = t;
                                         }
                                    break;
                                    case Centena:
                                       p = d - 1;
                                       t = V[ 30 + p ];
        
                                       if( n % 100  == 0 )
                                       { s = ""; e = ""; } 
                                       else
                                         if( d == 1 ) t += "to"; 
                                      
                                       s = t + e + s;                                      
                                       z = ( s + z );  
                                    break;         
                                } 
                               
                                e = " ";    
                              //ini. calcula los miles, millones, billones
                                r = l - i;                               
                                if( r > 0 && r % 3 == 0  ){
                                        p = ( r > 2 )?  2 : j++ & 1;    
                                        t = V[ 40 + p ];
                                       
                                        if( p > 0 )
                                           if( ( n == 1 && i > 1 ) || n > 1  ) t += "es";
                                       
                                        z = e + t + e + z;
                                }
                              //fin.
                                

                               //reinicia las variables
                               if ( u == Centena ){  u = 1;  n = 0;  s = "";  } else u *= 10;                                
                         }
                      
             }     

           //ini. adiciona la moneda y los centavos
                if ( !c.equals("") ) c = " con " + c + " centavos";           
                if ( !sMoney.equals("") )       
                    sMoney = " " + sMoney;
                else
                    if( b > 0 ) z += "o"; 
           //fin.
           
            z = ( s + z ) + sMoney + c;
      }
      catch(NumberFormatException ex){
            z = "ERROR [readNumber]: Formato numerico incorrecto.";
      }
     
     return z;
    
   }

  
  
   private static String[] initVector(  ){
       String V[] = new String[43];
       
        V[0] = "cero";
        V[1] = "un";
        V[2] = "dos";
        V[3] = "tres";
        V[4] = "cuatro";
        V[5] = "cinco";
        V[6] = "seis";
        V[7] = "siete";
        V[8] = "ocho";
        V[9] = "nueve";
        V[10] = "diez";
        V[11] = "once";
        V[12] = "doce";
        V[13] = "trece";
        V[14] = "catorce";
        V[15] = "quince";
        V[16] = "dieciseis";
        V[17] = "diecisiete";
        V[18] = "dieciocho";
        V[19] = "diecinueve";
        V[20] = "veinte";
        V[21] = "treinta";
        V[22] = "cuarenta";
        V[23] = "cincuenta";
        V[24] = "secenta";
        V[25] = "setenta";
        V[26] = "ochenta";
        V[27] = "noventa";
        V[28] = "";
        V[29] = "";
        V[30] = "cien";
        V[31] = "doscientos";
        V[32] = "trescientos";
        V[33] = "cuatrocientos";
        V[34] = "quinientos";
        V[35] = "seiscientos";
        V[36] = "setecientos";
        V[37] = "ochocientos";
        V[38] = "novecientos";
        V[39] = "";
        V[40] = "mil";
        V[41] = "millon";
        V[42] = "billon";
       
        return V;
   }


}





 este tambien lo hice es a misma version pero en visual vb 6 y sin algunos ajustes que tiene el anterior JAVA





Const Unidad = 1
Const Decena = 10
Const Centena = 100
Const UMil = 1000
Const CMil = 100000
Const Millon = 1000000
Const UMMillon = 1000000000
Const CMMillon = 100000000000#
Const MMMillon = 1000000000000#



' CONVIERTE DE NUMERO A TEXTO
Public Function cvtNumTxt(Numero) As Variant
Const b = 10
Dim C, R, U, S, P, T, D, M, K, V()

Call LLenarVector(V)

C = Numero
L = False
U = 1
M = 1

If C <> "" Then
  If C > 0 Then
     Do
            P = ""
            R = ModL(C, b)
            C = Int(C / b)
            T = T + R * U
       
           ' VERIFICA LAS UNIDADES, DECENAS, CENTENAS
            If R > 0 Then
                Select Case U
                    Case Unidad
                        If M > 100 Then _
                           V(1) = "Un"
                        D = V(T)
                        If C = 0 Then P = D
                    Case Decena
                        If R = 1 Then
                          P = V(T)
                        Else
                          P = V(20 + (R - 2))
                          If T Mod b > 0 Then
                            If T >= 30 Then
                              P = P & " y " & D
                            Else
                              P = "Veinti" & LCase(D)
                            End If
                          End If
                        End If
                        P = " " & P
                    Case Centena
                        P = V(30 + (R - 1))
                        If T > 100 And T < 200 Then _
                           P = P & "to"
                        P = " " & P
               End Select
            Else
              If U = b Then P = " " & D
            End If
   
            If M > 100 Then
                ' VERIFICA LAS UNIDADES DE MIL, MILLONES Y BILLONES
                  Select Case M
                     Case UMil To CMil, UMMillon To CMMillon
                      If U = 1 And R = 1 Then P = ""
                        If T > 0 And K = 0 Then
                         P = P & " Mil"
                         K = 1
                       End If
                     Case Millon
                       P = P & " Millon"
                       If Not (T = 1 And C = 0) Then _
                           P = P & "es"
                       K = 0
                     Case MMMillon
                       P = P & " Billon"
                       If Not (T = 1 And C = 0) Then _
                            P = P & "es"
                       M = 1
                 End Select
              End If
            
            If U = Centena Then
                U = 1
                T = 0
                D = ""
            Else
               U = U * b
            End If
   
                     
        M = M * b
        S = P & S
                               
      Loop While (C <> 0)
           
    Else
       S = V(0)
    End If
End If

cvtNumTxt = Trim(S)

End Function



' PERMITE INTRODUCIR NUMEROS MAYORES A 1000 MILLONES PARA SOLUCIONAR ERROR EN MOD
Public Function ModL(Num1, Num2) As Variant
ModL = Num1 - (Int(Num1 / Num2) * Num2)
End Function




Private Sub LLenarVector(ByRef Vec)

ReDim Vec(43)

Vec(0) = "Cero"
Vec(1) = "Uno"
Vec(2) = "Dos"
Vec(3) = "Tres"
Vec(4) = "Cuatro"
Vec(5) = "Cinco"
Vec(6) = "Seis"
Vec(7) = "Siete"
Vec(8) = "Ocho"
Vec(9) = "Nueve"
Vec(10) = "Diez"
Vec(11) = "Once"
Vec(12) = "Doce"
Vec(13) = "Trece"
Vec(14) = "Catorce"
Vec(15) = "Quince"
Vec(16) = "Dieciseis"
Vec(17) = "Diecisiete"
Vec(18) = "Dieciocho"
Vec(19) = "Diecinueve"
Vec(20) = "Veinte"
Vec(21) = "Treinta"
Vec(22) = "Cuarenta"
Vec(23) = "Cincuenta"
Vec(24) = "Secenta"
Vec(25) = "Setenta"
Vec(26) = "Ochenta"
Vec(27) = "Noventa"
Vec(28) = ""
Vec(29) = ""
Vec(30) = "Cien"
Vec(31) = "Doscientos"
Vec(32) = "Trescientos"
Vec(33) = "Cuatrocientos"
Vec(34) = "Quinientos"
Vec(35) = "Seiscientos"
Vec(36) = "Setecientos"
Vec(37) = "Ochocientos"
Vec(38) = "Novecientos"

End Sub