¿Cómo convertir un número decimal a binario y viceversa en PL/SQL?

Si alguna vez se encontraron en la necesidad de convertir un número decimal a binario y viceversa, se habrán dado cuenta que Oracle no incluye una función para poder realizarlo fácilmente.

Solamente existe la función "bin_to_num", la cual tiene el siguiente funcionamiento:

BIN_TO_NUM( expr1, expr2, ... expr_n)

Donde expr1, expr2, ... expr_n deben ser "0" o "1".

Es por esto que decidí crear las siguientes funciones:
"FNC_NUMBER_TO_BINARY" y "FNC_NUMBER_FROM_BINARY".

Para hacerlo me basé en unas funciones que encontré en este link, pero corrigiéndoles algunas cosas que no funcionaban adecuadamente.

El código

La función "FNC_NUMBER_TO_BINARY" es así:

CREATE OR REPLACE FUNCTION FNC_NUMBER_TO_BINARY ( p_numero IN NUMBER )
RETURN NUMBER
IS
 
l_max          NUMBER;
l_resultado    NUMBER         := ABS ( p_numero );
l_binario      VARCHAR2(4000) := '0';
l_signo        NUMBER;
 
BEGIN
 
-- -----------------------------------------------------
-- Determinar la cantidad de dígitos del número binario
-- -----------------------------------------------------
l_max      := FLOOR ( LN ( ABS ( p_numero ) ) / LN(2) );
 
-- -----------------------------------------------------
-- Determinar el signo
-- -----------------------------------------------------
IF p_numero >= 0 THEN
 
l_signo := 1;
 
ELSE
 
l_signo := -1;
 
END IF;
 
-- -----------------------------------------------------
-- Procesar número hasta obtener binario de l_max dígitos
-- -----------------------------------------------------
FOR i IN REVERSE 0..l_max LOOP
 
-- -----------------------------------------------------
-- Si el número parcial es mayor al dígito correspondiente
-- -----------------------------------------------------
IF l_resultado >= POWER ( 2, i ) THEN
 
-- -----------------------------------------------------
-- Agregar un '1' al final del binario
-- -----------------------------------------------------
l_binario   := l_binario || '1';
 
-- -----------------------------------------------------
-- Restar del resultado parcial el dígito correspondiente
-- -----------------------------------------------------
l_resultado := l_resultado - POWER ( 2, i );
 
ELSE
 
-- -----------------------------------------------------
-- En caso de que el número parcial sea menor al dígito
-- correspondiente, agregar un '0' al final del binario
-- -----------------------------------------------------
l_binario := l_binario || '0';
 
END IF;
 
END LOOP;
 
-- -----------------------------------------------------
-- En caso de que el número original sea potencia de dos
-- lo trato en forma separada
-- -----------------------------------------------------
IF ABS (p_numero) = POWER ( 2, l_max + 1) THEN
 
l_binario := '1';
 
-- -----------------------------------------------------
-- Completar con '0' a la derecha hasta formar el número
-- binario
-- -----------------------------------------------------
FOR i IN 1..l_max + 1 LOOP
 
l_binario := l_binario || '0';
 
END LOOP;
 
END IF;
 
-- -----------------------------------------------------
-- Retornar el número obtenido multiplicado por
--  el signo correspondiente
-- -----------------------------------------------------
RETURN TO_NUMBER ( l_binario ) * l_signo;
 
END FNC_NUMBER_TO_BINARY;

Nota: Cabe aclarar que la función toma la parte entera del número que se le pase a la misma.

Y por último adjunto el código de "FNC_NUMBER_FROM_BINARY":

CREATE OR REPLACE FUNCTION FNC_NUMBER_FROM_BINARY ( p_numero IN NUMBER )
RETURN NUMBER
IS
 
l_posicion     NUMBER         := 0;
l_binario      VARCHAR2(4000);
l_resultado    NUMBER         := 0;
l_signo        NUMBER;
 
BEGIN
 
-- -----------------------------------------------------
-- Si el número recibido es nulo, retornar -1
-- -----------------------------------------------------
IF p_numero IS NULL THEN
 
RETURN -1;
 
END IF;
 
-- -----------------------------------------------------
-- Quedarse con el valor entero, sin espacios, del
-- número recibido
-- -----------------------------------------------------
l_binario := LTRIM ( RTRIM ( TO_CHAR ( ABS ( p_numero ) ) ) );
 
-- -----------------------------------------------------
-- Determinar el signo
-- -----------------------------------------------------
IF p_numero >= 0 THEN
 
l_signo := 1;
 
ELSE
 
l_signo := -1;
 
END IF;
 
-- -----------------------------------------------------
-- Procesar uno por uno los caracteres del binario
-- y sumarlos al número a devolver
-- -----------------------------------------------------
FOR i IN 1..LENGTH ( l_binario ) LOOP
 
l_resultado := l_resultado + ( SUBSTR ( l_binario, i, 1 ) * POWER ( 2, LENGTH ( l_binario ) - i ) );
 
END LOOP;
 
-- -----------------------------------------------------
-- Retornar el número obtenido multiplicado por
--  el signo correspondiente
-- -----------------------------------------------------
RETURN l_resultado * l_signo;
 
END FNC_NUMBER_FROM_BINARY;

La ejecución

Podemos probar las funciones de la siguiente manera:

SELECT FNC_NUMBER_TO_BINARY(8) FROM dual;
SELECT FNC_NUMBER_FROM_BINARY(00001000) FROM dual;

Conclusión

Con estas dos funciones podemos realizar las conversiones que precisemos entre números decimales y binarios.

Les dejo el link por si las quieren descargar, son dos archivos .sql: [download id="11"]

Espero sus comentarios!

Esta entrada fue publicada en Oracle y etiquetada . Guarda el enlace permanente.

6 respuestas a ¿Cómo convertir un número decimal a binario y viceversa en PL/SQL?

  1. Alberto Gobbi dijo:

    Excelentes funciones :).
    Yo estaba trabajando con BIN_TO_NUM, pero era un fastidio tener que pasarle un arreglo de valores :s.

  2. Julio dijo:

    Perfecto!!!!!!!

    Como seria para convertir a Hexadecimales????

    Gracias

    • jic dijo:

      Julio, en este caso no te servirían estas funciones y deberías hacer unas nuevas… Si las llegás a desarrollar y las querés compartir contactame que las subimos. Gracias!

      • TöNé! dijo:

        De verdad que ayuda mucho; muchas gracias.

        Sólo un detalle muy importante en la parte de manejo de números negativos. El complemento a 2 brilló por su ausencia.

        Si queremos tener una función realmente genérica, habría que agregarlo, no basta con una multiplicación por “-1″ X-D

        Saludos

        • jic dijo:

          Tenés razón! Yo cuando la hice no la necesité en negativo, por eso no me preocupé. Si la querés corregir pasámela corregida que la subimos. Gracias por el aporte!

  3. portes dijo:

    el script es excelente, solo basta
    hacerle un menu y jala de maravilla…
    graciasssss

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>