Skip to content

Instantly share code, notes, and snippets.

@leog1992
Last active April 7, 2024 05:45
Show Gist options
  • Save leog1992/f96596d93b3ff4105ed7affa724f415f to your computer and use it in GitHub Desktop.
Save leog1992/f96596d93b3ff4105ed7affa724f415f to your computer and use it in GitHub Desktop.
Clase para convertir numeros a letras en JAVA.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package clases;
import java.util.regex.Pattern;
/**
*
* @author CALIDAD
*/
public class Numero_Letras {
private final String[] UNIDADES = {"", "un ", "dos ", "tres ", "cuatro ", "cinco ", "seis ", "siete ", "ocho ", "nueve "};
private final String[] DECENAS = {"diez ", "once ", "doce ", "trece ", "catorce ", "quince ", "dieciseis ",
"diecisiete ", "dieciocho ", "diecinueve", "veinte ", "treinta ", "cuarenta ",
"cincuenta ", "sesenta ", "setenta ", "ochenta ", "noventa "};
private final String[] CENTENAS = {"", "ciento ", "doscientos ", "trecientos ", "cuatrocientos ", "quinientos ", "seiscientos ",
"setecientos ", "ochocientos ", "novecientos "};
public Numero_Letras() {
}
public String Convertir(String numero, boolean mayusculas) {
String literal = "";
String parte_decimal;
//si el numero utiliza (.) en lugar de (,) -> se reemplaza
numero = numero.replace(".", ",");
//si el numero no tiene parte decimal, se le agrega ,00
if (numero.indexOf(",") == -1) {
numero = numero + ",00";
}
//se valida formato de entrada -> 0,00 y 999 999 999,00
if (Pattern.matches("\\d{1,9},\\d{1,2}", numero)) {
//se divide el numero 0000000,00 -> entero y decimal
String Num[] = numero.split(",");
//de da formato al numero decimal
parte_decimal = "y " + Num[1] + "/100 Soles.";
//se convierte el numero a literal
if (Integer.parseInt(Num[0]) == 0) {//si el valor es cero
literal = "cero ";
} else if (Integer.parseInt(Num[0]) > 999999) {//si es millon
literal = getMillones(Num[0]);
} else if (Integer.parseInt(Num[0]) > 999) {//si es miles
literal = getMiles(Num[0]);
} else if (Integer.parseInt(Num[0]) > 99) {//si es centena
literal = getCentenas(Num[0]);
} else if (Integer.parseInt(Num[0]) > 9) {//si es decena
literal = getDecenas(Num[0]);
} else {//sino unidades -> 9
literal = getUnidades(Num[0]);
}
//devuelve el resultado en mayusculas o minusculas
if (mayusculas) {
return (literal + parte_decimal).toUpperCase();
} else {
return (literal + parte_decimal);
}
} else {//error, no se puede convertir
return literal = null;
}
}
/* funciones para convertir los numeros a literales */
private String getUnidades(String numero) {// 1 - 9
//si tuviera algun 0 antes se lo quita -> 09 = 9 o 009=9
String num = numero.substring(numero.length() - 1);
return UNIDADES[Integer.parseInt(num)];
}
private String getDecenas(String num) {// 99
int n = Integer.parseInt(num);
if (n < 10) {//para casos como -> 01 - 09
return getUnidades(num);
} else if (n > 19) {//para 20...99
String u = getUnidades(num);
if (u.equals("")) { //para 20,30,40,50,60,70,80,90
return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8];
} else {
return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8] + "y " + u;
}
} else {//numeros entre 11 y 19
return DECENAS[n - 10];
}
}
private String getCentenas(String num) {// 999 o 099
if (Integer.parseInt(num) > 99) {//es centena
if (Integer.parseInt(num) == 100) {//caso especial
return " cien ";
} else {
return CENTENAS[Integer.parseInt(num.substring(0, 1))] + getDecenas(num.substring(1));
}
} else {//por Ej. 099
//se quita el 0 antes de convertir a decenas
return getDecenas(Integer.parseInt(num) + "");
}
}
private String getMiles(String numero) {// 999 999
//obtiene las centenas
String c = numero.substring(numero.length() - 3);
//obtiene los miles
String m = numero.substring(0, numero.length() - 3);
String n = "";
//se comprueba que miles tenga valor entero
if (Integer.parseInt(m) > 0) {
n = getCentenas(m);
return n + "mil " + getCentenas(c);
} else {
return "" + getCentenas(c);
}
}
private String getMillones(String numero) { //000 000 000
//se obtiene los miles
String miles = numero.substring(numero.length() - 6);
//se obtiene los millones
String millon = numero.substring(0, numero.length() - 6);
String n = "";
if (millon.length() > 1) {
n = getCentenas(millon) + "millones ";
} else {
n = getUnidades(millon) + "millon ";
}
return n + getMiles(miles);
}
}
@cdellano
Copy link

Les comparto la solución a otro detalle; es con la secuencia del 21 al 29.

El código original lo escribe erróneamente como sigue a continuación:
21 -> VEINTE Y UN (lo correcto es VEINTIÚN ó VEINTIUNO)
22 -> VEINTE Y DOS (lo correcto es VEINTIDÓS)
23 -> VEINTE Y TRES (lo correcto es VEINTITRÉS)
24 -> VEINTE Y CUATRO (lo correcto es VEINTICUATRO)
25 -> VEINTE Y CINCO (lo correcto es VEINTICINCO)
26 -> VEINTE Y SEIS (lo correcto es VEINTISÉIS)
27 -> VEINTE Y SIETE (lo correcto es VEINTISIETE)
28 -> VEINTE Y OCHO (lo correcto es VEINTIOCHO)
29 -> VEINTE Y NUEVE (lo correcto es VEINTINUEVE)

Sólo sustituyan el método getDecenas(String num) por el código de abajo:

private String getDecenas(String num) {// 99 int n = Integer.parseInt(num); if (n < 10) {//para casos como -> 01 - 09 return getUnidades(num); } else if (n > 19) {//para 20...99 String u = getUnidades(num); if (u.equals("")) { //para 20,30,40,50,60,70,80,90 return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8]; } else { if(n == 21) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 22) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 23) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 24) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 25) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 26) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 27) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 28) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} if(n == 29) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8] + "y " + u; } } else {//numeros entre 11 y 19 return DECENAS[n - 10]; } }

Agradezco enormemente tu aportación @leog1992 leog1992

@testingSec
Copy link

testingSec commented Jan 21, 2022

Buen dia a todos, muchas gracias por los aportes, son muy utiles.
Mejore un poco la version, le quite la limitacion de rango de integer, le agregue soporte para billones y otras mejoras mas.
Paso por parametro los plurales y singulares de los enteros y los flotantes para que se pueda acomodar a pesos, soles, dolares, libras, etc....
lo tengo funcionando y lo estamos homologando...
Paso la version:


package xxxxx.utils;

import java.math.BigInteger;
import java.util.regex.Pattern;

// Funcion para convertir un nro que representa dinero en pesos a letras.-
// Funcion mejorada de la que se publico en https://gist.github.com/leog1992/f96596d93b3ff4105ed7affa724f415f
// Sin la limitacion del rango de integer, soporte de billones y mejoras varias.
// Se acomoda a cualquier moneda, referencias en:
// https://es.wikipedia.org/wiki/Cent%C3%A9simo_(fracci%C3%B3n_monetaria)

public class NumeroLetras {

private final String[] UNIDADES = {"", "un ", "dos ", "tres ", "cuatro ", "cinco ", "seis ", "siete ", "ocho ", "nueve "};
private final String[] DECENAS = {"diez ", "once ", "doce ", "trece ", "catorce ", "quince ", "dieciseis ",
    "diecisiete ", "dieciocho ", "diecinueve", "veinte ", "treinta ", "cuarenta ",
    "cincuenta ", "sesenta ", "setenta ", "ochenta ", "noventa "};
private final String[] CENTENAS = {"", "ciento ", "doscientos ", "trecientos ", "cuatrocientos ", "quinientos ", "seiscientos ",
    "setecientos ", "ochocientos ", "novecientos "};

public NumeroLetras() {
}

public String Convertir(String numero, String etiquetaEnteroSingular,String etiquetaEnteroPlural, String etiquetaFlotanteSingular,String etiquetaFlotantePlural, String etiquetaConector, boolean mayusculas) {
    String literal = "";
    String parte_decimal = "";
    //si el numero utiliza (.) en lugar de (,) -> se reemplaza
    numero = numero.replace(".", ",");
    //si el numero no tiene parte decimal, se le agrega ,00
    if (numero.indexOf(",") == -1) {
        numero = numero + ",00";
    }
    //se valida formato de entrada -> 0,00 y 999 999 999 999,00
    if (Pattern.matches("\\d{1,12},\\d{1,2}", numero)) {
        //se divide el numero 0000000,00 -> entero y decimal
        String Num[] = numero.split(",");
        //de da formato al numero decimal
        if (Num[1].length()==1) {
        	Num[1] += "0";
        }                        
        String d = getDecenas(Num[1]);
        if (d!="") {
        	if (etiquetaEnteroSingular!="") parte_decimal += " ";
        	if (Integer.parseInt(Num[1])==1) {
        		parte_decimal += etiquetaConector + " " + d + etiquetaFlotanteSingular;
        	} else {
        		parte_decimal += etiquetaConector + " " + d + etiquetaFlotantePlural;
        	}
        }
        
        //se convierte el numero a literal                       
		BigInteger parteEntera = new BigInteger(Num[0]);
       
        if (parteEntera.compareTo(new BigInteger("0")) == 0) {//si el valor es cero
            literal = "cero ";
        } else if (parteEntera.compareTo(new BigInteger("999999999")) == 1 ) {//si es billon
            literal = getBillones(Num[0]);
        } else if (parteEntera.compareTo(new BigInteger("999999")) == 1 ) {//si es millon
            literal = getMillones(Num[0]);
        } else if (parteEntera.compareTo(new BigInteger("999")) == 1 ) {//si es miles
            literal = getMiles(Num[0]);
        } else if (parteEntera.compareTo(new BigInteger("99")) == 1 ) {//si es centena
            literal = getCentenas(Num[0]);
        } else if (parteEntera.compareTo(new BigInteger("9")) == 1 ) {//si es decena
            literal = getDecenas(Num[0]);
        } else {//sino unidades -> 9
            literal = getUnidades(Num[0]);
        }
        //devuelve el resultado en mayusculas o minusculas
        
        if (parteEntera.compareTo(new BigInteger("1")) == 0) {
        	literal += etiquetaEnteroSingular;            	
        } else {
        	literal += etiquetaEnteroPlural;
        }            
        
        if (mayusculas) {
            return (literal + parte_decimal).toUpperCase();
        } else {
            return (literal + parte_decimal);
        }
    } else {//error, no se puede convertir
        return literal = null;
    }
}

/* funciones para convertir los numeros a literales */
private String getUnidades(String numero) {// 1 - 9
    //si tuviera algun 0 antes se lo quita -> 09 = 9 o 009=9
    String num = numero.substring(numero.length() - 1);
    return UNIDADES[Integer.parseInt(num)];
}

private String getDecenas(String num) {// 99 
	int n = Integer.parseInt(num); 
	if (n < 10) {//para casos como -> 01 - 09 
		return getUnidades(num); 
	} else if (n > 19) {//para 20...99 
		String u = getUnidades(num); 
		if (u.equals("")) { //para 20,30,40,50,60,70,80,90 
			return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8]; 
		} else { 
			if(n == 21) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 22) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 23) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 24) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 25) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 26) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 27) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;}
			if(n == 28) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} 
			if(n == 29) {return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8].substring(0,5) + "i" + u;} 
			return DECENAS[Integer.parseInt(num.substring(0, 1)) + 8] + "y " + u; 
		} 
	} else {//numeros entre 11 y 19 
		return DECENAS[n - 10];
	} 
}

private String getCentenas(String num) {// 999 o 099
    if (Integer.parseInt(num) > 99) {//es centena
        if (Integer.parseInt(num) == 100) {//caso especial
            return " cien ";
        } else {
            return CENTENAS[Integer.parseInt(num.substring(0, 1))] + getDecenas(num.substring(1));
        }
    } else {//por Ej. 099 
        //se quita el 0 antes de convertir a decenas
        return getDecenas(Integer.parseInt(num) + "");
    }
}

private String getMiles(String numero) {// 999 999
    //obtiene las centenas
    String c = numero.substring(numero.length() - 3);
    //obtiene los miles
    String m = numero.substring(0, numero.length() - 3);
    String n = "";
    //se comprueba que miles tenga valor entero
    if (Integer.parseInt(m) > 0) {
        n = getCentenas(m);
        return n + "mil " + getCentenas(c);
    } else {
        return "" + getCentenas(c);
    }

}

private String getMillones(String numero) { //000 000 000        
    //se obtiene los miles
    String miles = numero.substring(numero.length() - 6);
    //se obtiene los millones
    String millon = numero.substring(0, numero.length() - 6);
    String n = "";
    if (Integer.parseInt(millon) > 0) {
    	if (Integer.parseInt(millon) == 1) {
    		n = getUnidades(millon) + "millon ";
    	} else {
    		n = getCentenas(millon) + "millones ";
    	}
    }
    
    return n + getMiles(miles);
}

private String getBillones(String numero) { //000 000 000 000        
    //se obtiene los miles
    String miles = numero.substring(numero.length() - 9);
    //se obtiene los millones
    String millon = numero.substring(0, numero.length() - 9);
    String n = "";
    if (Integer.parseInt(millon) == 1) {
    	n = getUnidades(millon) + "billon ";
    } else {
    	n = getCentenas(millon) + "billones ";
    }
    
    return n + getMillones(miles);
}

}


CONTROLADOR PARA TESTEAR Y MOSTRAR IMPLEMENTACION:

package xxxxx.controllers.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xxxxx.utils.NumeroLetras;

@RestController
@RequestMapping("/api/v1/numeroLetra")
public class NumeroLetrasController {
private final static Logger logger = LoggerFactory.getLogger(NumeroLetrasController.class);

@GetMapping("/")
public ResponseEntity<String> get(String numero, String etiquetaEnteroSingular,String etiquetaEnteroPlural, String etiquetaFlotanteSingular,String etiquetaFlotantePlural, String etiquetaConector, boolean mayusculas) {
	logger.info("numeroLetra/?numero=" + numero + "&etiquetaEntero=" + etiquetaEnteroSingular + "&etiquetaFlotante="+etiquetaFlotanteSingular+ "&etiquetaConector="+etiquetaConector+ "&mayusculas="+mayusculas);
	NumeroLetras letritas = new NumeroLetras();
	String result = letritas.Convertir(numero, etiquetaEnteroSingular, etiquetaEnteroPlural, etiquetaFlotanteSingular, etiquetaFlotantePlural, etiquetaConector, mayusculas);		
	logger.info( result );       	
    return new ResponseEntity<String>(result, HttpStatus.OK);
}

}

@Cdca12
Copy link

Cdca12 commented Mar 21, 2023

Gracias por el aporte. Me sacaste de un apuro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment