Numeros a letras
From PostgreSQL wiki
Números a letras
Works with PostgreSQL
Any version
Written in
PL/pgSQL, PL/Perl
Depends on
Nothing
Contents |
These functions takes a number as argument and returns a spanish string representing the number.
Estas funciones reciben un número como argumento y retorna su representación en palabras.
Función fu_numero_letras (numero numeric) RETURNS text
Esta función fue publicada por Javier Bermúdez en convertir numeros a letras
CREATE OR REPLACE FUNCTION fu_numero_letras(numero numeric) RETURNS text AS $body$ DECLARE lnEntero INTEGER; lcRetorno TEXT; lnTerna INTEGER; lcMiles TEXT; lcCadena TEXT; lnUnidades INTEGER; lnDecenas INTEGER; lnCentenas INTEGER; lnFraccion INTEGER; lnSw INTEGER; BEGIN lnEntero := FLOOR(numero)::INTEGER;--Obtenemos la parte Entera lnFraccion := FLOOR(((numero - lnEntero) * 100))::INTEGER;--Obtenemos la Fraccion del Monto lcRetorno := ''; lnTerna := 1; IF lnEntero > 0 THEN lnSw := LENGTH(lnEntero); WHILE lnTerna <= lnSw LOOP -- Recorro terna por terna lcCadena = ''; lnUnidades = lnEntero % 10; lnEntero = CAST(lnEntero/10 AS INTEGER); lnDecenas = lnEntero % 10; lnEntero = CAST(lnEntero/10 AS INTEGER); lnCentenas = lnEntero % 10; lnEntero = CAST(lnEntero/10 AS INTEGER); -- Analizo las unidades SELECT CASE /* UNIDADES */ WHEN lnUnidades = 1 AND lnTerna = 1 THEN 'UNO ' || lcCadena WHEN lnUnidades = 1 AND lnTerna <> 1 THEN 'UN ' || lcCadena WHEN lnUnidades = 2 THEN 'DOS ' || lcCadena WHEN lnUnidades = 3 THEN 'TRES ' || lcCadena WHEN lnUnidades = 4 THEN 'CUATRO ' || lcCadena WHEN lnUnidades = 5 THEN 'CINCO ' || lcCadena WHEN lnUnidades = 6 THEN 'SEIS ' || lcCadena WHEN lnUnidades = 7 THEN 'SIETE ' || lcCadena WHEN lnUnidades = 8 THEN 'OCHO ' || lcCadena WHEN lnUnidades = 9 THEN 'NUEVE ' || lcCadena ELSE lcCadena END INTO lcCadena; /* UNIDADES */ -- Analizo las decenas SELECT CASE /* DECENAS */ WHEN lnDecenas = 1 THEN CASE lnUnidades WHEN 0 THEN 'DIEZ ' WHEN 1 THEN 'ONCE ' WHEN 2 THEN 'DOCE ' WHEN 3 THEN 'TRECE ' WHEN 4 THEN 'CATORCE ' WHEN 5 THEN 'QUINCE ' ELSE 'DIECI' || lcCadena END WHEN lnDecenas = 2 AND lnUnidades = 0 THEN 'VEINTE ' || lcCadena WHEN lnDecenas = 2 AND lnUnidades <> 0 THEN 'VEINTI' || lcCadena WHEN lnDecenas = 3 AND lnUnidades = 0 THEN 'TREINTA ' || lcCadena WHEN lnDecenas = 3 AND lnUnidades <> 0 THEN 'TREINTA Y ' || lcCadena WHEN lnDecenas = 4 AND lnUnidades = 0 THEN 'CUARENTA ' || lcCadena WHEN lnDecenas = 4 AND lnUnidades <> 0 THEN 'CUARENTA Y ' || lcCadena WHEN lnDecenas = 5 AND lnUnidades = 0 THEN 'CINCUENTA ' || lcCadena WHEN lnDecenas = 5 AND lnUnidades <> 0 THEN 'CINCUENTA Y ' || lcCadena WHEN lnDecenas = 6 AND lnUnidades = 0 THEN 'SESENTA ' || lcCadena WHEN lnDecenas = 6 AND lnUnidades <> 0 THEN 'SESENTA Y ' || lcCadena WHEN lnDecenas = 7 AND lnUnidades = 0 THEN 'SETENTA ' || lcCadena WHEN lnDecenas = 7 AND lnUnidades <> 0 THEN 'SETENTA Y ' || lcCadena WHEN lnDecenas = 8 AND lnUnidades = 0 THEN 'OCHENTA ' || lcCadena WHEN lnDecenas = 8 AND lnUnidades <> 0 THEN 'OCHENTA Y ' || lcCadena WHEN lnDecenas = 9 AND lnUnidades = 0 THEN 'NOVENTA ' || lcCadena WHEN lnDecenas = 9 AND lnUnidades <> 0 THEN 'NOVENTA Y ' || lcCadena ELSE lcCadena END INTO lcCadena; /* DECENAS */ -- Analizo las centenas SELECT CASE /* CENTENAS */ WHEN lnCentenas = 1 AND lnUnidades = 0 AND lnDecenas = 0 THEN 'CIEN ' || lcCadena WHEN lnCentenas = 1 AND NOT(lnUnidades = 0 AND lnDecenas = 0) THEN 'CIENTO ' || lcCadena WHEN lnCentenas = 2 THEN 'DOSCIENTOS ' || lcCadena WHEN lnCentenas = 3 THEN 'TRESCIENTOS ' || lcCadena WHEN lnCentenas = 4 THEN 'CUATROCIENTOS ' || lcCadena WHEN lnCentenas = 5 THEN 'QUINIENTOS ' || lcCadena WHEN lnCentenas = 6 THEN 'SEISCIENTOS ' || lcCadena WHEN lnCentenas = 7 THEN 'SETECIENTOS ' || lcCadena WHEN lnCentenas = 8 THEN 'OCHOCIENTOS ' || lcCadena WHEN lnCentenas = 9 THEN 'NOVECIENTOS ' || lcCadena ELSE lcCadena END INTO lcCadena;/* CENTENAS */ -- Analizo la terna SELECT CASE /* TERNA */ WHEN lnTerna = 1 THEN lcCadena WHEN lnTerna = 2 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN lcCadena || ' MIL ' WHEN lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND lnUnidades = 1 AND lnDecenas = 0 AND lnCentenas = 0 THEN lcCadena || ' MILLON ' WHEN lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND NOT (lnUnidades = 1 AND lnDecenas = 0 AND lnCentenas = 0) THEN lcCadena || ' MILLONES ' WHEN lnTerna = 4 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN lcCadena || ' MIL MILLONES ' ELSE '' END INTO lcCadena;/* TERNA */ --Retornamos los Valores Obtenidos lcRetorno = lcCadena || lcRetorno; lnTerna = lnTerna + 1; END LOOP; END IF; IF lnTerna = 1 THEN lcRetorno := 'CERO'; END IF; lcRetorno := RTRIM(lcRetorno) || ' CON ' || LTRIM(lnFraccion) || '/100 NUEVOS SOLES'; RETURN lcRetorno; END; $body$ LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER; COMMENT ON FUNCTION fu_numero_letras(numero numeric) IS 'Funcion para Convertir el Monto Numerico a Letras';
Función f_convnl(num numeric) RETURNS character varying
Otra función con el mismo propósito utilizando otra técnica de programación.
Autora: Conxita Marín
CREATE FUNCTION f_convnl(num numeric) RETURNS character varying AS $$ -- Función que devuelve la cadena de texto en castellano que corresponde a un número. -- Parámetros: número con 2 decimales, máximo 999.999.999,99. DECLARE d VARCHAR[]; f VARCHAR[]; g VARCHAR[]; numt VARCHAR; txt VARCHAR; a INTEGER; a1 INTEGER; a2 INTEGER; n INTEGER; p INTEGER; negativo BOOLEAN; BEGIN -- Máximo 999.999.999,99 IF num > 999999999.99 THEN RETURN '---'; END IF; txt = ''; d = ARRAY[' un',' dos',' tres',' cuatro',' cinco',' seis',' siete',' ocho',' nueve',' diez',' once',' doce',' trece',' catorce',' quince', ' dieciseis',' diecisiete',' dieciocho',' diecinueve',' veinte',' veintiun',' veintidos', ' veintitres', ' veinticuatro', ' veinticinco', ' veintiseis',' veintisiete',' veintiocho',' veintinueve']; f = ARRAY ['','',' treinta',' cuarenta',' cincuenta',' sesenta',' setenta',' ochenta', ' noventa']; g= ARRAY [' ciento',' doscientos',' trescientos',' cuatrocientos',' quinientos',' seiscientos',' setecientos',' ochocientos',' novecientos']; numt = LPAD((num::numeric(12,2))::text,12,'0'); IF strpos(numt,'-') > 0 THEN negativo = TRUE; ELSE negativo = FALSE; END IF; numt = TRANSLATE(numt,'-','0'); numt = TRANSLATE(numt,'.,',''); -- Trato 4 grupos: millones, miles, unidades y decimales p = 1; FOR i IN 1..4 LOOP IF i < 4 THEN n = substring(numt::text FROM p FOR 3); ELSE n = substring(numt::text FROM p FOR 2); END IF; p = p + 3; IF i = 4 THEN IF txt = '' THEN txt = ' cero'; END IF; IF n > 0 THEN -- Empieza con los decimales txt = txt || ' con'; END IF; END IF; -- Centenas IF n > 99 THEN a = substring(n::text FROM 1 FOR 1); a1 = substring(n::text FROM 2 FOR 2); IF a = 1 THEN IF a1 = 0 THEN txt = txt || ' cien'; ELSE txt = txt || ' ciento'; END IF; ELSE txt = txt || g[a]; END IF; ELSE a1 = n; END IF; -- Decenas a = a1; IF a > 0 THEN IF a < 30 THEN IF a = 21 AND (i = 3 OR i = 4) THEN txt = txt || ' veintiuno'; ELSIF n = 1 AND i = 2 THEN txt = txt; ELSIF a = 1 AND (i = 3 OR i = 4)THEN txt = txt || ' uno'; ELSE txt = txt || d[a]; END IF; ELSE a1 = substring(a::text FROM 1 FOR 1); a2 = substring(a::text FROM 2 FOR 1); IF a2 = 1 AND (i = 3 OR i = 4) THEN txt = txt || f[a1] || ' y' || ' uno'; ELSE IF a2 <> 0 THEN txt = txt || f[a1] || ' y' || d[a2]; ELSE txt = txt || f[a1]; END IF; END IF; END IF; END IF; IF n > 0 THEN IF i = 1 THEN IF n = 1 THEN txt = txt || ' millón'; ELSE txt = txt || ' millones'; END IF; ELSIF i = 2 THEN txt = txt || ' mil'; END IF; END IF; END LOOP; txt = LTRIM(txt); IF negativo = TRUE THEN txt= '-' || txt; END IF; RETURN txt; END; $$ LANGUAGE plpgsql;
Con el módulo Perl Lingua::ES::Numeros
CREATE OR REPLACE num2pal(numeric) RETURNS text LANGUAGE plperlu as $$ use Lingua::ES::Numeros; $obj = new Lingua::ES::Numeros('FORMATO' => 'con %s.'); return $obj->real($_[0]); $$;