[C] Raiz Cuadrada sin math.h

Iniciado por edr89, 19 Mayo 2013, 08:22 AM

0 Miembros y 1 Visitante están viendo este tema.

edr89

Hola,
Necesito calcular la raiz cuadrada de un numero, encontre en la red una funcion que no necesita de la libreria math.h, todo ejecuta pero no termino de entender el for loop de la raiz:

#include<stdio.h>
#include<conio.h>

float SquareRoot(float num);
void main()
        {
        int input;
        float square;
        printf("Escribe el numero: ");
        scanf("%d",&input);
            if(input<0)
            {
                printf("La raiz de un numero negativo no esta definida, por favor intenta de nuevo.");
            }

        square = SquareRoot(input);
        printf("\n La raiz de %d es: %.5f",input, square);
        getch();
        }

float SquareRoot(float num)
{
    float x = num;
    if(num >= 0)
        {
            int i;
            for(i = 0; i < 20; i ++)

            x = (((x * x) + num) / (2 * x));

            return x;
        }
}


¿Porqué i<20?, num es el dato que el usuario va a teclear que es = x, entonces mientras el loop corre ¿qué le pasa a x?

x1 = las operaciones indicadas con el dato que escribe el usuario.
x2 = las mismas operaciones ahora con el nuevo dato resultado de x1.
x3 = operaciones con el dato que se genero en x2.
xn = ...

es asi como sucede?

sospecho que la condicion en for() y la expresion de X se reducen a meras formulas matematicas, no recuerdo muy bien como resolver una raiz cuadrada con precision y cifras significativas.

Trato de pensar en alguna funcion que resuelva con dos numeros de raiz entera como (4, 9) para buscar raices en dicho intervalo. La cuestion es que no puedo usar sqrt() de math.h.

Sugerencias bienvenidas!

Shell Root

No se como será eso, pero se supone que expresar la raiz cuadrada de un numero es igual a la potenciación con exponente ½, es decir,




Más fácil por ahí?

:http://es.wikipedia.org/wiki/Ra%C3%ADz_cuadrada
Por eso no duermo, por si tras mi ventana hay un cuervo. Cuelgo de hilos sueltos sabiendo que hay veneno en el aire.

leosansan

#2
Cita de: edr89 en 19 Mayo 2013, 08:22 AM
Hola,
Necesito calcular la raiz cuadrada de un numero, encontre en la red una funcion que no necesita de la libreria math.h, todo ejecuta pero no termino de entender el for loop de la raiz:

El 20del for es como un número mínimo de aproximaciones sucesivas. En realidad está mal implementado el código ya que en números pequeños se alcanza el valor correcto en la  tercerao cuarta iteración o aproximación, resultando inútiles las demás, dependiendo el número de aproximaciones del tamaño del numero. Más bien debería de comparar el valor de x calculado con el anterior y si son iguales se acaba.

Por ejemplo, la salida para raiz de 2 es:

Código (cpp) [Seleccionar]
Escribe el numero: 2
La raiz de 2 es: 1.500000
La raiz de 2 es: 1.416667
La raiz de 2 es: 1.414216
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214

La raiz de 2 es: 1.41421


Fíjate que en la cuarta ya se tiene el valor deseado resultando inútiles las demás.


Citar
¿Porqué i<20?, num es el dato que el usuario va a teclear que es = x, entonces mientras el loop corre ¿qué le pasa a x?

x1 = las operaciones indicadas con el dato que escribe el usuario.
x2 = las mismas operaciones ahora con el nuevo dato resultado de x1.
x3 = operaciones con el dato que se genero en x2.
xn = ...

es asi como sucede?


Tal y com ves en la salida que te he puesto, es así.

Citar
sospecho que la condicion en for() y la expresion de X se reducen a meras formulas matematicas, no recuerdo muy bien como resolver una raiz cuadrada con precision y cifras significativas.

La condición del for es una chapuza, ya te comente que debería ser mejor con un while comparando valor actual y valor anterior, es un número el 20 de "mínimos" para asegurar la convergencia para números muy grandes, pero para números cortos es demasiado elevado. Y el valor de x es que el que resulta de un cálculo "a mano", mira en Wikipedia que lo explica bien.


Observa en cambio ésta salida y compárala con la original:

Código (cpp) [Seleccionar]
Escribe el numero: 2
La raiz de 2 es: 1.500000
La raiz de 2 es: 1.416667
La raiz de 2 es: 1.414216
La raiz de 2 es: 1.414214
La raiz de 2 es: 1.414214

La raiz de 2 es: 1.41421


Como ves he comparado cada valor obtenido en cada iteración con el anterior y en el momento que son iguales paro. Me ahorro unas cuantitas iteraciones. Y el código, con una pequeña modificación para evitar bucles si en lugar de un número se introduce una letra:

Código (cpp) [Seleccionar]
#include<stdio.h>
#include <stdlib.h>

float SquareRoot(float num);
void main()
       {
       int input,cont;
       char ch;
       float square;
       do {
           cont=0
           printf("Escribe el numero: ");
           cont=scanf("%d",&input);
           while( (ch = getchar()) != '\n' );
           if(input<=0)
               printf("La raiz de un numero negativo no esta definida, por favor intenta de nuevo.\n");
       }while (cont==0 || input<=0);
       square = SquareRoot(input);
       printf("\n La raiz de %d es: %.5f",input, square);
       getch();
       }

float SquareRoot(float num)
{
   float x = num,x1;
   int i;
   do{
       x1=x;
       x = (((x * x) + num) / (2 * x));
       printf(" La raiz de %g es: %f\n",num, x);
   }while (x!=x1);
   return x;
}


Citar
Trato de pensar en alguna funcion que resuelva con dos numeros de raiz entera como (4, 9) para buscar raices en dicho intervalo. La cuestion es que no puedo usar sqrt() de math.h.

Tendrías que escanear dos números en lugar de uno y usando un for pasar los  números comprendidos entre esos dos a la función

y meter el código que te calculala raiz en un for que va desde num1 a num2. Una salida a esta opción sería:

Código (cpp) [Seleccionar]
Escribe el primer numero: 2
Escribe el segundo numero: 16

La raiz de 2 es: 1.41421
La raiz de 3 es: 1.73205
La raiz de 4 es: 2.00000
La raiz de 5 es: 2.23607
La raiz de 6 es: 2.44949
La raiz de 7 es: 2.64575
La raiz de 8 es: 2.82843
La raiz de 9 es: 3.00000
La raiz de 10 es: 3.16228
La raiz de 11 es: 3.31662
La raiz de 12 es: 3.46410
La raiz de 13 es: 3.60555
La raiz de 14 es: 3.74166
La raiz de 15 es: 3.87298
La raiz de 16 es: 4.00000


con el siguiente código:

Código (cpp) [Seleccionar]

#include<stdio.h>
#include <stdlib.h>

float SquareRoot(float num);
void main()
       {
       int flag1=0,flag2=0,num1,num2,cont1,cont2,i;
       chat ch;
       float square;
       do {
           cont1=cont2=flag1=flag2=0;
           printf("Escribe el primer numero: ");
           cont1=scanf("%d",&num1);
           if (cont1==0)
               flag1++;
           while( (ch = getchar()) != '\n' );
           printf("Escribe el segundo numero: ");
           cont2=scanf("%d",&num2);
           if (cont2==0)
               flag1++;
           while( (ch = getchar()) != '\n' );
           if(num1<=0 || num2<=0){
               printf("La raiz de un numero negativo no esta definida, por favor intenta de nuevo.\n");
               flag2++;
           }

       }while (flag1!=0 || flag2!=0);
       for (i=num1;i<=num2;i++){
           square = SquareRoot(i);
           printf("\n La raiz de %d es: %.5f",i, square);
       }
}

float SquareRoot(float num)
{
   float x = num,x1;
   int i;
   do{
       x1=x;
       x = (((x * x) + num) / (2 * x));
       //printf(" La raiz de %g es: %f\n",num, x);
   }while (x!=x1);
   return x;



}


Está hecho a toda pastilla, por lo que habría que testearlo un poco a ver si falla o no, pero para que veas más o menos como sería la cosa.

Saluditos!. .... ..

edr89

Cita de: leosansan en 19 Mayo 2013, 12:39 PM
Está hecho a toda pastilla, por lo que habría que testearlo un poco a ver si falla o no, pero para que veas más o menos como sería la cosa.

Ambos códigos funcionan, el primero solo te faltó un cierre de instrucción, me has dejado boquiabierto!, lo reviso con tiempo para poder entenderlo, el segundo código era una idea solamente, en realidad el programa debe dar la raiz del numero tecleado, ademas que es un poco mas elaborado y no entiendo ciertas partes. :(

Estuve buscando sin exito como evitar el bucle infinito cuando se teclea un caracter y no un numero, tengo varios archivos con esa falla, con un do-while lo soluciono no?

do
{
...
}while( (ch = getchar()) != '\n' );


Saludos!!

leosansan

Cita de: edr89 en 19 Mayo 2013, 22:52 PM

Estuve buscando sin exito como evitar el bucle infinito cuando se teclea un caracter y no un numero, tengo varios archivos con esa falla, con un do-while lo soluciono no?

do
{
...
}while( (ch = getchar()) != '\n' );



Es la forma más corriente de hacerlo, aunque puede estar más elaborada con una variable cont que cuente las lecturas que hace scanf, que es lo que utilizo en el código que te pase junto con el mencionada while. Realmente es una forma de limpiar lo que se llama buffer o memoria intermedia por decirlo a lo breve.

Saluditos! ..... ...nuevamente!!!!



edr89