sábado, 23 de octubre de 2010

.: ¿Números Primos en Python o en C? :.

:: Detección de Números Primos ::



Materia. Lab de Leng de Progr

Hora. V1(Jueves)

En esta entrada, hablaremos sobre unas pequeñas comparaciones en cuestión de un código que se realizó para la exposición en la clase ordinaria para el tema de iteración.
Hablaremos de cómo se aprecia el mismo programa en lenguaje C y en Python. Me refiero al programa para la detección de Números Primos.
Códigos Implementados en:
Pero antes, prefiero platicar de la forma en la cual definimos un número primo. Pues me parece que di la explicación un poco rápido en la clase.
Todos sabemos que un número primo es aquel que es divisible exactamente entre sí mismo y el número 1. Sin embargo, todo número entero es divisible de esta manera. Entonces habría que pensar los casos en los cuales puede ser divisible entre otro número distinto de los ya expuestos.
Es aquí donde surge un caso base, en cual por definición, cualquier número en el cual su residuo por la división entre dos sea cero, y mientras sea diferente de dos, no puede ser primo, pues tiene más factores que lo dividen exactamente. Es decir, aquí se define que ningún número que sea par puede ser primo, a excepción del número dos que si es primo.
Entonces reducimos nuestras posibilidades de números primos, dejándonos sólo los números impares. Pero da la casualidad que no todos los números impares son primos.
Entonces, ¿qué podemos hacer aquí? Bueno, para empezar podríamos intentar hacer divisiones del número que deseamos consultar entre puros números impares, como el 3, 5, 11, 17… de modo que comprobemos si alguno de esos números puede llegar a dividirlo.
Este podría ser el caso del número 17 por decir algo, pues se va dividiendo entre número enteros impares sin pasarse del 17… y vemos que ningún número impar menor a 17 lo puede dividir exactamente.
Para poder lograr estas divisiones utilizamos un FOR que vaya desde el número 3 hasta el número N que estamos analizando y nuestro contador se incremente de dos en dos, dentro del cual utilizamos un IF que tenga la condición de que si nuestro número N es divisible entre el número impar que se esté trabajando en ese momento, me diga que NO es primo.
Pero OJO, ¿no se les hace muy deficiente hacer tantas divisiones hasta llegar al número N cuando hablamos de número más grandes que sólo un simple 17?
Por ejemplo, nosotros tenemos en número 141. Nuestro caso base de los números pares no de afectará, por lo que entrara al proceso de las divisiones con los números impares.
Antes de que lo olvide, manejamos una instrucción break, dentro del proceso de las divisiones para que en el primer factor impar que pueda dividir nuestro número se quiebre el proceso del FOR y no continúe haciendo divisiones.
Volviendo a la explicación con el 141, estábamos diciendo que tendrían que hacerse muchas divisiones.
Entonces tenemos un pequeño dato, condición, etc. (como gusten verlo), la cual me dice que cualquier número N que no tenga factores antes de la raíz cuadrada de ese mismo número, puede concluirse que sí es primo.
Demostración.
Caso 1.
Nosotros tenemos el número 141. Si obtenemos los factores que dividen a ese número, tenemos los siguientes:
1, 3, 47, 141
Como pueden ver, cada factor tiene su pareja correspondiente de modo que al multiplicarse uno con el otro, nos dan el resultado de 141.
Si separamos el número de factores que tiene el número 141 por la mitad tendríamos lo siguiente:
1, 3 --->>>PUNTO MEDIO <<--- 47, 141.
Como pueden darse cuenta, demostramos lo que se dijo sobre lo de las parejas. Si tenemos un número antes de ese punto medio que pueda dividir a nuestro número a analizar, es porque del otro lado tenemos a su pareja correspondiente para que al multiplicarse nos dé el número a analizar.
De lo contrario, si no tenemos ningún otro número además del 1 que divida a nuestro número N es porque del otro lado no tiene pareja de tipo entera para que pueda multiplicarse y darnos el número N.
Por consiguiente, sólo queda definir, ¿qué representa ese punto medio del cual hemos hablado tanto? Representa la raíz cuadra del número N.
1, 3 --->> 11.874342 <<--- 47, 141.
Caso 2
Veamos nuestro número súper famoso: 17. Los factores quedarían:
1, 17
1 --->> PUNTO MEDIO <<--- 17
1 --->> 4.1231 <<--- 17
Por consiguiente vemos que no hay ningún factor antes de la raíz cuadrada además del 1, por lo que el 17 si es primo.
Conclusión
Gracias a lo anterior ahora decimos que nuestras divisiones entre números impares va a ir desde 3 hasta .
Noten que estamos manejando números enteros, por lo que no importa si la raíz es decimal, nuestro programa manejara sólo el entero que salga.
Ahora bien, desde el inicio del programa manejamos la variable fact = 0 como el contador que nos dice si el número N tiene más de un factor que lo divide además del 1 y el mismo número N.
Al finalizar el FOR que manipula las divisiones, si nunca entro al proceso IF dentro de él, llegará a otro IF aparte que me preguntara si fact = 0; de ser así, el número SI es primo.
De lo contrario, si se llegó a entrar al IF dentro del FOR de las divisiones, la variable fact cambiará su valor. Será fact = 1. De modo que al llegar al segundo IF que define cuando el SI es primo, no muestre ese mensaje.
Si no hiciera esto, puede que mi programa llegue a mostrarme que un número N NO es primo y luego que SI es primo.
Aquí se muestra el código que hace todo el proceso mencionado desde el caso base de los números impares:
if ((num % 2 == 0) && (num != 2)) {
           printf("\nEl numero %d NO es primo", num);
       } else {
          for (i = 3; i <= (sqrt(num)); i+= 2) {             
              if (num % i == 0) {                     
                       printf("\nEl numero %d NO es primo", num);
                       fac = 1;
                       break;
              }  
          }
         
          if (fac == 0) {
                   printf("\nEl numero %d SI es primo", num);
          }        
       }
En fin, terminando con este rollo, hablemos de lo importante en este, que es la comparación de las implementaciones en C y en Python.
Primeramente, nuestra implementación en C (33 líneas) es la siguiente:
#include <stdio.h>

int main(void) {
   int num, i, fac = 0, r;
  
   do {
       printf("Dame el numero: ");
       scanf("%d", &num);
  
       if ((num % 2 == 0) && (num != 2)) {
           printf("\nEl numero %d NO es primo", num);
       } else {
          for (i = 3; i <= (sqrt(num)); i+= 2) {             
              if (num % i == 0) {                     
                       printf("\nEl numero %d NO es primo", num);
                       fac = 1;
                       break;
              }  
          }
         
          if (fac == 0) {
                   printf("\nEl numero %d SI es primo", num);
          }        
       }
      
       printf("\n\nDesea consultar otro numero? SI (1) NO (0):\n");
       scanf("%d", &r);
      
   }while(r == 1);
  
   return 0;
}
Y nuestra implementación en Python (25 líneas) sería:
#!/usr/bin/python

print "\nDEFINICION DE NUMEROS PRIMOS"

r = 1     <<--- Utilizado para poder entrar al proceso del WHILE

while r == 1:       <<--- Esto es sólo para ciclar el programa.
    N = input("\nDame el numero a analizar: ")
    i = 3
    fact = 0

    if (N % 2 == 0) and (N != 2):
        print "\nEl numero %d NO es primo\n" % N
    else:
        while i <= (N**0.5):
            if (N % i) == 0:
                print "\nEl numero %d NO es primo\n" % N
                fact = 1
                break
            i+=2

        if fact == 0:
            print "\nEl numero %d SI es primo\n" % N
   
    r = input("Consultar otro numero? SI (1) o NO (0)--->> ")
A fin de cuentas, no tenemos mucho que decir. Para empezar, en Python manejamos menos líneas de código.
La verdad es que la facilidad del manejo del código se aprecia mucho más cuando lo estas haciendo.
Pero si se dan cuenta, el código en Python se ve un poco más fácil de leer. Hasta hace parecer el programa más fácil de lo que es.
En lo personal, ya con el hecho de no manejar tantos puntos y comas ( ; ) al final de cada línea y sin poner tantas llaves, veo el código más legible y limpio.
Yo me quedaba con el código hecho en Python. ¡Definitivo!
La verdad no sé qué opinen ustedes como lectores.
Lo que también me agrada en Python es que no te la quiebras tanto con el formato de variables y con lo que ya había mencionado antes: con lo de las llaves de inicio y cierre.
Ya ven que luego nos salen errores en C de entrada y salida. Sé que se escucha a que me da flojera un programa en C, pero simplemente digamos que la realidad es que Python sólo nos facilita a no equivocarnos en cosas de este tipo.
Cualquier cosa que desean aportar acerca de esta comparación adelante.
También si deseas preguntar algo sobre el programa que se tomó para la comparación, bienvenida es.
De cualquier manera aquí les dejo el link de la clase que expusimos mis compañeros y yo en la clase ordinaria por si desean revisarla.
Saludos a todos.

1 comentario: