[Ayuda novato] Raiz cuadrada en C sin sqrt

Iniciado por bourne1191, 6 Diciembre 2013, 11:55 AM

0 Miembros y 4 Visitantes están viendo este tema.

bourne1191

Hola! soy nuevo por aqui. Estoy estudiando ingeniería, y en una asignatura de informática han mandado hacer un programa para calcular la raíz cuadrada de un número real N sin usar la funcion sqrt sin la libreria math. Entonces, pensé en hacer una iteracíon desde i=0.1 a i=X hasta que i*i=>N... pero no me salen las cosas como quiero. os pongo el código;

#include<stdio.h>

void main(void)
{
float n,res;
float i=0;
printf ("Introduzca variable n\n");
scanf ("%f",&n);

do
{
i= i+0.1;
res= i*i;
}while (res>=n);

printf ("\nLa raíz cuadrada de %f es %f",n,i);

getch();
}


sabéis ayudarme de alguna manera? gracias!

ivancea96

#include<stdio.h>

void main(void)
{
float n,res;
float i=0;
printf ("Introduzca variable n\n");
scanf ("%f",&n);

do
{
i= i+0.1;
res= i*i;
}while (n>=res);

printf ("\nLa raíz cuadrada de %f es %f",n,i);

getch();
}


Pusiste "}while (res>=n);" en vez de "}while (n>=res);".

Está bien el algoritmo. Podrías pensar en darle más precisión, como haciendo que vaya de 0.01 en 0.01.
Pero bueno, solo es eso.

Suerte

amchacon

#2
Cita de: ivancea96 en  6 Diciembre 2013, 12:24 PM
Está bien el algoritmo. Podrías pensar en darle más precisión, como haciendo que vaya de 0.01 en 0.01.
Pero bueno, solo es eso.

Suerte

Con todo el respeto del mundo, ese algoritmo es una auténtica caca. Primero porque es muy lento (ponle la raíz de 500 a ver que tal), segundo porque es muy poco preciso.

Lo que te están pidiendo esque hagas las series de taylor, la raíz de x puede expresarse como el limite de la siguiente sucesión:

Citara(0) = 0
a(1) = (1+x) / 2
a(n) = (a(n-1)+x/a(n-1))/2

Siendo x el número del que quieres obtener la raíz. El error con el que estás calculando la raíz puede expresarse como:

Citara(n)-a(n-1)

De modo que si quieres calcular de raíz de un numero con una precisión de 1e-15 (15 decimales de precisión). Tendrías que empezar en a(1) y ir aplicando la sucesión a(n). En cada calculo haces la resta con el valor anterior y paras cuando el error sea menor a 1e-15.

Ese es algoritmo que usa sqrt, debería darte el mismo resultado (puede variar en los decimales 16-17, pero es un error despreciable).

Pregunta si tienes alguna duda.

PD: No lo he dicho, pero para tener 15 decimales de precisión necesitaras usar double y no float
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

bourne1191

joder, que despiste... muchas gracias, a ver si voy corrigiendo estos errores tan tontos. un saludo!!

bourne1191

Cita de: amchacon en  6 Diciembre 2013, 12:41 PM
Con todo el respeto del mundo, ese algoritmo es una auténtica caca. Primero porque es muy lento (ponle la raíz de 500 a ver que tal), segundo porque es muy poco preciso.

Lo que te están pidiendo esque hagas las series de taylor, la raíz de x puede expresarse como el limite de la siguiente sucesión:

Siendo x el número del que quieres obtener la raíz. El error con el que estás calculando la raíz puede expresarse como:

De modo que si quieres calcular de raíz de un numero con una precisión de 1e-15 (15 decimales de precisión). Tendrías que empezar en a(1) y ir aplicando la sucesión a(n). En cada calculo haces la resta con el valor anterior y paras cuando el error sea menor a 1e-15.

Ese es algoritmo que usa sqrt, debería darte el mismo resultado (puede variar en los decimales 16-17, pero es un error despreciable).

Pregunta si tienes alguna duda.

PD: No lo he dicho, pero para tener 15 decimales de precisión necesitaras usar double y no float

buena respuesta.. por ahora estoy empezando con C y no sé como meter ese tipo de límites en el compilador, pero suena bastante interesante y me pondré a investigarlo. desde luego, mi algoritmo era un poco "de andar por casa"... saludos y gracias

amchacon

#5
Cita de: bourne1191 en  6 Diciembre 2013, 12:49 PM
buena respuesta.. por ahora estoy empezando con C y no sé como meter ese tipo de límites en el compilador, pero suena bastante interesante y me pondré a investigarlo. desde luego, mi algoritmo era un poco "de andar por casa"... saludos y gracias
Dudo que te pidan lo que has hecho en el primer post, lo más probable esque te pidan que hagas la raíz así. Es un problema típico de primero, probablemente también te pidan que calcules e^x y el seno también.

Si es un problema de primero, es porque no es tan complicado como parece. Lo que pasa esque como aparecen matemáticas asusta un poco. Planteatelo así, la serie se hace con un bucle y tres variables (una es el valor actual, que deberá valer:

double valor = (1+x)/2; // o en vez de x lo llamas n como en tú código

La otra es con el valor anterior, lo dejaremos a cero por el momento. La otra tendrá el error, que tendrá lo mismo que la variable valor.

Ahora tenemos que hacer un bucle, lo repetiremos mientras que (error > 1e-15). Recuerda que hemos dicho que vamos a dejar 15 decimales de precisión, si queremos menos se lo podemos cambiar, también puedes meterlo a mano si te resulta confuso lo de 1e-15:

while(error > 0.00000000000001

Ahora dentro del bucle, asignaremos a valor siguiendo la fórmula:

valor = (anterior+x/(anterior))/2;

Calcularemos el error:

error = valor-anterior;

Y actualizamos el anterior:

anterior = valor;

Y ya esta, prácticamente te he dicho todo. Tienes que unir todas las ideas que te he dicho. Después muestras valor por pantalla y san se acabó.
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

leosansan

#6
Cita de: bourne1191 en  6 Diciembre 2013, 11:55 AM
Hola! soy nuevo por aqui. Estoy estudiando ingeniería, y en una asignatura de informática han mandado hacer un programa para calcular la raíz cuadrada de un número real N sin usar la funcion sqrt sin la libreria math.................

Mira si te sirve de orientación:

raiz sin sqrt


do-while

#7
¡Buenas!

Mas sencillo que Taylor(Quien ha hablado de Taylor???  :silbar:). Con Bolzano puedes hacerlo perfectamente (o por el teorema de los valores intermedios). Ademas Bolzano lo has tenido que estudiar en bachiller y sabes como funciona. x es raiz cuadrada de c si y solo si c - x2 = 0

En principio solo tienes que calcular la raiz cuadrada positiva, por lo que una cota inferior de la raiz cuadrada siempre sera cero. Y como cota superior tienes dos opciones. Si c > 1, tomas como cota superior c, y si c<1 la cota superior escogida tiene que ser 1. Ten en cuenta que tienes dos casos particulares, que coinciden con los valores 0 y 1 que estas utilizando como cotas especificas, en los que sabes exactamente cual es el valor de la raiz.

Una vez comprobado que el valor del que quieres obtener la raiz cuadrada no es ni cero ni uno, empiezas a iterar:
- Calculas el punto medio del intervalo [cota_inferior,cota_superior]
- Si punto_medio al cuadrado > valor -> cota_superior = punto_medio
- Si punto_medio al cuadrado < valor -> cota_inferior = punto_medio
- Si punto medio al cuadrado = valor -> raiz_cuadrada = punto_medio
- Repetir mientras absoluto(valor - punto_medio al cuadrado) > error_que_yo_quiera.

En ocasiones puedes llegar a un punto que no sea la raiz pero que no cambie, asi que tambien deberias controlar que el punto medio de una iteracion no sea el mismo que el de la anterior. Si sucede esto ultimo, el valor que obtengas sera la mejor aproximacion que puedas conseguir.

¡Saludos!

Y si no quieres recurrir a metodos iterativos puedes usar el siguiente razonamiento:

x2 = c -> 2 Ln(x) = Ln(c) -> Ln(x) = Ln(c) / 2 -> x = eLn(c)/2

O equivalentemente x = blogb(c)/2

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

bourne1191

bueno escribo este post sin haberme leido las respuestas en profundidad, antes que nada agradeceros el esfuerzo, voy a mirarme seriamente e ir planteando todo, a ver que tal se da la cosa....