Divide y Venceras Análisis de Algoritmos

12
Análisis de Algoritmos Práctica 2: Divide y Vencerás Multiplicación de dos números binarios. por ESCAMILLA CAMACHO JUAN EDUARDO PEREZ PEREZ JOSÉ RICARDO DRA. GARCÍA MENDOZA CONSUELO VARINIA Profesor

description

Práctica sobre el análisis de Divide y venceras

Transcript of Divide y Venceras Análisis de Algoritmos

Page 1: Divide y Venceras Análisis de Algoritmos

Análisis de

Algoritmos

Práctica 2: Divide y Vencerás

Multiplicación de dos

números binarios.

por

ESCAMILLA CAMACHO JUAN

EDUARDO

PEREZ PEREZ JOSÉ RICARDO

DRA. GARCÍA MENDOZA

CONSUELO VARINIA

Profesor

Page 2: Divide y Venceras Análisis de Algoritmos

1

TABLA DE CONTENIDO

INTRODUCCIÓN............................................................................................................... 2

DESARROLLO .............................................................................................................. 3

A) TABLA ..........................................................ERROR! BOOKMARK NOT DEFINED.

B) GRÁFICA ............................................................................................................. 4

C) CUESTIONARIO .................................................................................................... 4

CONCLUSIONES........................................................................................................... 5

ANEXOS ..................................................................ERROR! BOOKMARK NOT DEFINED.

A) MULTIPLICACIÓN BINARIA: MÉTODO TRADICIONAL ........... ERROR! BOOKMARK NOT

DEFINED.

B) MULTIPLICACIÓN BINARIA: MÉTODO DE DIVIDE Y VENCERÁS. ... ERROR! BOOKMARK

NOT DEFINED.

C) MULTIPLICACIÓN BINARIA: MÉTODO DE GAUSS. .ERROR! BOOKMARK NOT DEFINED.

BIBLIOGRAFÍA .......................................................ERROR! BOOKMARK NOT DEFINED.

Page 3: Divide y Venceras Análisis de Algoritmos

2

INTRODUCCION

En la cultura popular, divide y vencerás hace referencia a un refrán que

implica resolver un problema difícil, dividiéndolo en partes más simples tantas

veces como sea necesario, hasta que la resolución de las partes se torna

obvia. La solución del problema principal se construye con las soluciones

encontradas.

En las ciencias de la computación, el término divide y vencerás (DYV) hace

referencia a uno de los más importantes paradigmas de diseño algorítmico. El

método está basado en la resolución recursiva de un problema dividiéndolo

en dos o más sub-problemas de igual tipo o similar. El proceso continúa hasta

que éstos llegan a ser lo suficientemente sencillos como para que se

resuelvan directamente. Al final, las soluciones a cada uno de los sub-

problemas se combinan para dar una solución al problema original.

Esta técnica es la base de los algoritmos eficientes para casi cualquier tipo de

problema como, por ejemplo, algoritmos de

ordenamiento (quicksort, mergesort, entre muchos otros), multiplicar números

grandes (Karatsuba), análisis sintácticos (análisis sintáctico top-down) y

la transformada discreta de Fourier.

Por otra parte, analizar y diseñar algoritmos de DyV son tareas que lleva

tiempo dominar. Al igual que en la inducción, a veces es necesario sustituir el

problema original por uno más complejo para conseguir realizar la recursión,

y no hay un método sistemático de generalización.

El nombre divide y vencerás también se aplica a veces a algoritmos que

reducen cada problema a un único subproblema, como la búsqueda

binaria para encontrar un elemento en una lista ordenada (o su equivalente

en computación numérica, el algoritmo de bisección para búsqueda de

raíces). Estos algoritmos pueden ser implementados más eficientemente que

los algoritmos generales de “divide y vencerás”; en particular, si es usando

una serie de recursiones que lo convierten en simples bucles. Bajo esta amplia

definición, sin embargo, cada algoritmo que usa recursión o bucles puede ser

tomado como un algoritmo de “divide y vencerás”. El nombre decrementa y

vencerás ha sido propuesta para la subclase simple de problemas.

La corrección de un algoritmo de “divide y vencerás”, está habitualmente

probada una inducción matemática, y su coste computacional se determina

resolviendo relaciones de recurrencia.

Page 4: Divide y Venceras Análisis de Algoritmos

3

1|DESARROLLO

Implementa los siguientes algoritmos:

Algoritmo 1. Multiplicación de dos números en base 2 por el método tradicional.

Algoritmo 2. Multiplicación de dos números en base 2 con Divide y Vencerás a través de

sus mitades.

Algoritmo 3. Multiplicación de dos números en base 2 con Divide y Vencerás a través de

mitades, utilizando el truco de Gauss para eliminar un producto.

A) TABLA DE COMPLEJIDAD

COMPLEJIDAD COMPLEJIDAD SIN

RECURSIVIDAD

Algoritmo 1 T(n) = n²+2n. T(n) = C1*0n+ C2*n11n+

C3*n21n+ C4*n31n+

C5*n41n+ C6*n51n.

Algoritmo 2 T(n) = 4T(n/2)+C. T(n) = C1*4log2

(n) +

C2*1log2

(n).

Algoritmo 3 T(n) = T(n)= 3T(n/2) +

C.

T(n) = C1*3log2

(n) +

C2*1log2

(n).

B) GRAFICA

GRAFICA COMPLEJIDAD MULTIPLICACION DE NUMEROS BINARIOS

NORMAL

Page 5: Divide y Venceras Análisis de Algoritmos

4

C) CUESTIONARIO

1. ¿La complejidad del algoritmo de la multiplicación por método tradicional

disminuye al implementarlo con la con la estrategia de Divide y Vencerás?

RESPUESTA:

SI, DISMINUYE YA QUE SE HACE RECURSIVO ES DECIR QUE SE REALIZA CON

MENOS CICLOS Y SE REDUCE POR QUE TIENE UNA FUNCIÓN EXCLUSIVA

PARA DIVIDIR ,

2. ¿La complejidad del algoritmo de la multiplicación con la estrategia de Divide y

Vencerás es menor cuando se disminuyen las llamadas recursivas en cada nivel

de recursividad, como se hizo con el truco de Gauss para disminuir una llamada

recursiva?

RESPUESTA:

SI, PORQUE EN EL ALGORITMO DE DIVIDE Y VENCERAS NORMAL SE RALIZA

4 RAMAS DEL ABROL PARA LA DIVISION Y CON GAUSS SE DESMINUYE YA

QUE DE 4 RAMAS SE OBTIENEN 3 RAMAS UNICAMENTE Y SE ELIMINA UN

CICLO RECURSIVO Y POR CONISGUIENTE SE DISMINUYE LA COMPELJIDAD.

3. Analizando la gráfica indique para el cual, el algoritmo de menor complejidad se

vuelve cota inferior de cada uno de los otros dos algoritmos.

RESPUESTA:

PUES DESPUES DE ANILIZAR EL ALGORTIMO 3 DE DIVIDE Y VENCERAS

CON EL METODO DE GAUSS SE VUELVE LA COTA INFERIOR DE LOS DEMAS

ALGORITMOS

4. ¿Cuál es el código más sencillo? ¿Por qué lo considera más sencillo?

RESPUESTA:

PUES EL CÓDIGO MAS SENCILLO ES EL PRIMER OSEA, EL PROGRAMA DE

MULTIPLICACION DE BINARIOS POR METODO TRADICIONAL YA QUE

OCUPAMOS EL METODO DE PROGRAMACION A NIVEL DE BITS Y OCUPAMOS

OPERACION DE COMPUERTAS LÓGICAS Y NO NECESITAMOS OCUAPAR UNA

FUNCION DE CONVERSION DE BINARIO A DECIMAL ESTO SE SUSTITUYO

Page 6: Divide y Venceras Análisis de Algoritmos

5

CON EL SIGNO DE CORRIMIENTO A LA IZQUIERDA “<<” Y CON ESTE EL

COMPILADOR AUTOMÁTICAMENTE LO CONVIERTE Y NO SE ENCESITA

LLENAR CON CEROS POR QUE AL PROGRAMA AL NIVEL DE BITS SE LLENA

CON CEROS , Y TODO EL PROGRAMA SE REALIZA CON 12 LINEAS DE CÓDIGO

APROXIMADAMENTE.

2|CONCLUSIONES

JUAN EDUARDO ESCAMILLA CAMACHO

El objetivo principal de este proyecto consistía en el análisis del Algoritmo Divide y

Vencerás pro medio de un software sobre el método de multiplicación de números binarios

utilizando 3 algoritmos son tres: Método normal, Divide y vencerás y Divide y Vencerás

por medio de Gauss.

Se utilizó un proceso de desarrollo específico y una herramienta que permite programar

diferentes aplicaciones en diferentes lenguajes NETBEANS Y CODEBLOCKS Esta

herramienta complementa el marco de trabajo para la reutilización de requisitos y

constituye la parte práctica de la misma práctica

El resultado de emplear esta método es poder reducir la complejidad de ciertos programas

utilizando este método el cual se ocupado desde hace mucho tiempo atrás, además de

reducir la complejidad reduce el tiempo de ejecución del mismo y la programación se

torna más sencilla ya que nos ahorramos código y ciclos ya que utilizamos clases en el caso

de Java y funciones en el caso de C en CodeBlocks.

PEREZ PEREZ JOSÉ RICARDO

Para esta práctica personalmente me fue muy interesante ya que al llevar 6 semestres en la

carrera jamás había entendido bien el funcionamiento de la recursividad y como se

implementaba. Al aplicar la regla de Divide y Vencerás y conocer cómo se implementa en

los sistemas me permitió darme una idea de cómo se pueden ahorrar bastantes líneas de

código y tiempo de desarrollo del programa así como la complejidad de los mismos.

Para los problemas a solucionar cada uno fue programado en un lenguaje de programación

distinto pero la base del algoritmo fue el mismo, para el primer problema la solución se dio

en el lenguaje C, para el segundo problema de multiplicación binaria se resolvió el

problema con C# y para el último y más difícil se tuvo que implementar la solución en

JAVA ya que al desarrollarlo en C# se presentó la problemática que al compilarlo y correrlo

este entraba en un bucle infinito y al implementar la solución en JAVA este ya no

presentaba tal problema.

Fue una experiencia grata el poder desarrollar esta práctica así como desarrollar el código

de la solución a nuestro problema, aunque fue un poco estresante el pensar la solución se

que es buena práctica para desarrollar nuestras habilidades en el análisis de algoritmos.

Page 7: Divide y Venceras Análisis de Algoritmos

6

3|ANEXOS

A) PRIMER ALGORITMO

#include<stdlib.h>

#include<conio.h>

#include<time.h>

#include <stdio.h>

#include <string.h>

main(){

int i,j,k,valor2,suma,resultado;

char *primernumero,*segundonumero;

primernumero=(char*)malloc(sizeof(char));//se regresa el puntero que se le

asigno para primernumero

segundonumero=(char*)malloc(sizeof(char));//se regresa el puntero que se le asigno

para segundonumero

for(;;){

resultado=0;

suma=0;

/* Pantalla de inicio. */

system( "COLOR 47" );

printf( "\n\t ****************************************\n" );

printf( "\n\n\t\t ESCUELA SUPERIOR DE COMPUTO\n\n", 224 );

printf( "\t\t ANALISIS DE ALGORITMOS", 214 );

printf( "\n\n\t\t ESCAMILLA CAMACHO JUAN EDUARDO" );

printf( "\n\n\t\t PEREZ PEREZ JOSE");

printf("\n\n\t\t PRODUCTO DE BINARIOS NORMAL \n\n",214);

printf( "\t ****************************************\n\n" );

Page 8: Divide y Venceras Análisis de Algoritmos

7

time_t ahora;

struct tm *fecha;

time( &ahora );

fecha = localtime( &ahora );

printf( "\t\t\t\t\t\t FECHA DE HOY( %d/%d/%d )\n" , fecha->tm_mday , fecha-

>tm_mon+1 , fecha->tm_year+1900 );

system( "PAUSE" );

system("cls");

int w=0,i=0;

char aux,aux_1[200];

system("cls");

system("COLOR 47");

printf( "\n\t

**********************************************************\n" );

printf(" \n\n\t\t MULTIPLICACION DE BINARIOS (OJALA ESTE BIEN

=P)\n\n\n",224 );

printf(" \n\n\t\t META NUMEROS EN BINARIOS\n\n\n",214);

printf("\t

**********************************************************\n\n");

system("cls");

printf("COLOCA EL NUMERO BINARIO: \n\n");

scanf("%s",primernumero);

system("cls");

printf("COLOCA EL NUMERO BINARIO: \n\n");

scanf("%s",segundonumero);

system("cls");

//system ("pause");

printf("BIEN EL PRIMER NUMERO QUE INGRESASTE FUE:

%s\n",primernumero);

Page 9: Divide y Venceras Análisis de Algoritmos

8

printf("BIEN EL SEGUNDO NUMERO QUE INGRESASTE FUE:

%s\n\n",segundonumero);

if(strlen(segundonumero) <= strlen(primernumero))

{

for(i=strlen(segundonumero)-1,k=0;i<=0;i--,k++){//se iguala i con la longitud de

segundo numero es decir lo que trae en el primer registro

for(j=strlen(primernumero)-1,valor2=0,suma=0;j<=0; j--,valor2++)//se iguala j con

el tamaño de la cadena cuando se ingreso al segundo valor

suma|=( ( (segundonumero[i]&1)&(primernumero[j]&1) )<<valor2 );// como se

trabaja a nivel de bits ocupasmos operacion booleanas

resultado+=(suma<<k);

}

}else{

printf("");

}

for(i=strlen(segundonumero)-1,k=0;i>=0;i--,k++){//se iguala i con la longitud de

segundo numero es decir lo que trae en el primer registro

for(j=strlen(primernumero)-1,valor2=0,suma=0;j>=0; j--,valor2++)//se iguala j con

el tamaño de la cadena cuando se ingreso al segundo valor

suma|=( ( (segundonumero[i]&1)&(primernumero[j]&1) )<<valor2 );// como se

trabaja a nivel de bits ocupasmos operacion booleanas

resultado+=(suma<<k);//primeramente se realiza la multplicacion de numeros

bianrios por medio de la and y se almacena en un arreglo unidemensional cada numero

// entonces el resultado se desplaza a la izquiera y con el operador |= se realiza la

suma con la operacion que salga y nos da el resutlado

// << Este operador binario realiza un desplazamiento de bits a la izquierda. El bit

más significativo (más a la izquierda) se pierde, y se le asigna un 0 al menos significativo

(el de la derecha). El operando derecho indica el número de desplazamientos que se

realizarán.

//Recuérdese que los desplazamientos no son rotaciones; los bits que salen por la

izquierda se pierden, los que entran por la derecha se rellenan con ceros. Este tipo de

desplazamientos

//se denominan lógicos en contraposición a los cíclicos o rotacionales.

//el compilador realiza una conversion automatica de tipo

Page 10: Divide y Venceras Análisis de Algoritmos

9

}

printf("\nBIEN EL RESULTADO DE TU MULTIPLICACION ES LA SIGUIENTE:

%d\n",resultado);

system("pause");

}

}/*End main*/

B) SEGUNDO ALGORITMO

public int PDyV (int[]a,int[]b){ //Recibe dos matrices de tipo entero cada una

Operacion o = new Operacion (); //Declaramos un objeto de nuestra clase Operacion que

es donde se encuentran todos nuestros métodos a utilizar

int n,p,q,w;

int[] ai,ad,bi,bd;

n = a.Length; //n toma el tamaño de nuestro primer arreglo

if (a.Length == 1 && b.Length == 1) { //Si ambos arreglos recibidos son de tamaño uno

se multiplican entre si.

return o.productoMatrices(a,b);

} else {

//Se declaran nuestros arreglos en donde se guardaran nuestras divisiones ai, ad y bi y bd

ai = new int[a.Length/2];

ad = new int[a.Length/2];

bi = new int[b.Length/2];

bd = new int[b.Length/2];

ai = o.divide (a, 1);

Page 11: Divide y Venceras Análisis de Algoritmos

10

ad = o.divide (a, 2);

bi = o.divide (b, 1);

bd = o.divide (b, 2);

q = Convert.ToInt32 (Math.Pow (2, n));

w = Convert.ToInt32 (Math.Pow (2, n / 2));

//Se retorna la operación final del algoritmo aplicando recursividad con los valores

obtenidos de ai,ad,bi y bd

return (q*PDyV(ai,bi)) + (w*PDyV(ai,bd)) + (w*PDyV(ad,bi)) + (PDyV(ad,bd));

}

}

C) TERCER ALGORITMO

//Se reciben dos String donde se encuentran nuestros valores y la base (2)

int multiplicaBase(String a, String b, int base){

//Declaramos un objeto de nuestra clase Operacion que es donde se encuentran todos

nuestros métodos a utilizar

Operacion o = new Operacion();

String xi,xd,yi,yd,x,y;

int p1,p2,p3,p4,mayor;

if(a.length()==1 && b.length()==1){

{ //Si ambos arreglos recibidos son de tamaño uno se multiplican entre si.

return Integer.parseInt(a,base)*Integer.parseInt(b,base);

}

else{

//Se declaran nuestros arreglos en donde se guardaran nuestras divisions ai,ad y bi y bd

xi=o.divide(a,1);

xd=o.divide(a,2);

Page 12: Divide y Venceras Análisis de Algoritmos

11

yi=o.divide(b,1);

yd=o.divide(b,2);

x=Integer.toString((Integer.parseInt(xi, base)+Integer.parseInt(xd, base)),base);

y=Integer.toString((Integer.parseInt(yi, base)+Integer.parseInt(yd, base)),base);

mayor=o.obtenMayor(Integer.parseInt(x,base),Integer.parseInt(y,base));

x=o.acompleta(x,mayor,base);

y=o.acompleta(y,mayor,base);

p1=multiplicaBase(xi,yi,base);

p2=multiplicaBase(xd,yd,base);

p3=multiplicaBase(x, y, base);

//Se retorna la operación final del algoritmo aplicando recursividad con los valores

obtenidos de ai,ad,bi y bd

return ((int)Math.pow(base, a.length())*p1)+((int)Math.pow(base,

a.length()/2)*(p3-p2-p1))+p2;

}

}