Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: AlbertoBSD en 1 Mayo 2016, 23:14 pm



Título: Optimizando función manual de modulo o resto.
Publicado por: AlbertoBSD en 1 Mayo 2016, 23:14 pm
En su momento mas de alguno uso el operador modulo

r = a % n;

donde r es el resto de la división a/n donde n != 0

Ahora como estoy trabajando con numeros muy grandes de longitud variable el operador modulo como tal no me sirve, necesito crear la funcion que haga el modulo manualmente.

Si alguno de ustedes se perdio los temas, estos son algunos de ellos

Números de longitud variable en C (Numeros muy grandes) (http://foro.elhacker.net/programacion_cc/numeros_de_longitud_variable_en_c_numeros_muy_grandes-t451749.0.html)
Restas manuales en "Binario" (http://foro.elhacker.net/programacion_cc/restas_manuales_en_binario-t451768.0.html)

Ahora si hacemos la funcion modulo en forma de restas, tenemos solo le tenemos que restar al numero a el valor de n hastra que a sea menor que n

El siguiente codigo es muestra de ello de forma manual y sin ninguna optimizacion.

Código
  1. #include<stdio.h>
  2.  
  3. int main() {
  4. int resto,a,n,contador;
  5. a = 9999998;
  6. n = 3;
  7. resto = a;
  8. contador = 0;
  9. while(resto >= n) {
  10. resto-= n;
  11. contador++;
  12. }
  13. printf("resto: %u\nVeces en el ciclo %u\n",resto,contador);
  14. }

Salida:

Código:
resto: 2
Veces en el ciclo 3333332

Como vemos el numero de veces que entra al ciclo es el resultado de la división obtenido de forma iterativa mediante restas sucesivas.

Pero como se trata solo de la función "Modulo" o "Resto" no nos interesa el resultado de la división, para fines prácticos y rápidos realice esa función un poco mas optimizada y se podría optimizar mas, pero ya lo dejo a su consideración.

Código
  1. #include<stdio.h>
  2.  
  3. int main() {
  4. int resto,a,n,contador,n_pivote,resto_pivote,entrar;
  5. a = 9999998;
  6. n = 3;
  7. resto = a;
  8. contador = 0;
  9. resto_pivote = resto;
  10. n_pivote = n;
  11. entrar = 1;
  12. while(entrar && resto >= n) {
  13. resto_pivote-=n_pivote;
  14. if(resto_pivote>=0) {
  15. resto = resto_pivote;
  16. n_pivote*=2;
  17. }
  18. else {
  19. if(n_pivote > n) {
  20. n_pivote/=2;
  21. resto_pivote = resto;
  22. }
  23. else {
  24. entrar = 0;
  25. }
  26. }
  27. contador++;
  28. }
  29. printf("resto: %u\nVeces en el ciclo %u\n",resto,contador);
  30. }

Salida:

Código:
resto: 2
Veces en el ciclo 65

Como vemos el numero de veces que entra es muchísimo menor incluso si optimizamos mas la función para este ejemplo podremos llegar hasta solo 55 o 58 veces entrando al ciclo dado.

El programa utilizada una aproximación binaria ya que en cada iteracion al numero a se le resta un valor igual a n*2 veces la cantidad del ciclo anterior.

Dado que estoy trabajando con numero descomunalmente grandes... cualquier optimizan en estas funciones es mas que bien recibida.

Saludos!



Optimize aun mas el Código y ahora solo se ejecuta 42 veces para el ejemplo dado.

Ahora en lugar de incrementar el sustraendo dentro del ciclo principal lo incremento al máximo en un ciclo aparte antes del principal y posteriormente dentro del ciclo principal lo decremento hasta que sea el un multiplo de n inmediamtamente menor al valor actual de r

Código
  1. #include<stdio.h>
  2.  
  3. int main() {
  4. int resto,a,n,contador,n_pivote,entrar;
  5. a = 9999998;
  6. n = 3;
  7. resto = a;
  8. contador = 0;
  9. n_pivote = n;
  10. entrar = 1;
  11. while(n_pivote<resto) {
  12. n_pivote+=n_pivote;
  13. contador++;
  14. }
  15. while(entrar && resto >= n) {
  16. while(n_pivote>resto && n_pivote>n) {
  17. n_pivote/=2;
  18. contador++;
  19. }
  20. resto-=n_pivote;
  21. }
  22. printf("resto: %u\nVeces en el ciclo %u\n",resto,contador);
  23. }

Salida:

Código:
resto: 2
Veces en el ciclo 42

Considero yo que es el mas optimizado pero no se tal vez se puede ahorrar alguno que otro ciclo, la variable contador solo es para fines didácticos.

Saludos


Título: Re: Optimizando función manual de modulo o resto.
Publicado por: HardForo en 4 Mayo 2016, 20:00 pm
Buen trabajo! ese tipo de cosas (complejidad de los algortimos) son de las mas importantes y pocos programadores le dan la importancia que se merecen  ;-)