Comparación de funciones y punto flotante

#include<stdio.h>
#include<stdlib.h>
#define abs(a) ((a)>0 ? a: -a)
#define eps_sqrt 0.00000000000001
#define it 100

float sqrt(float x)
/*The Square Root Function using the Newton's Method*/
{
    int it_sqrt=0;
    float a_sqrt = x/2;
    while ((abs((a_sqrt*a_sqrt)-(x))>=eps_sqrt) && (2.0*a_sqrt != 0) && (it_sqrt<=it))
    {
        a_sqrt = a_sqrt - ((a_sqrt*a_sqrt)-(x)/(2.0*a_sqrt));
        it_sqrt++;
    }
    return a_sqrt;
}

int main()
{
    printf("%.5f\n", sqrt(5));
    system ("pause");
}

i tried using the Newton's iteration method to find the square root on Python and it worked, perfectly well. I'm new on C and I don't understand why this function didn't work for me. Whenever I run it, it returns "-1.#INF0A" Any help will be appreciated.


Edit: I tried changin the eps to 0.000001 y tampoco funcionó.

preguntado el 03 de mayo de 12 a las 17:05

I tried that but it still gives the same result -

wrong macro function abs argument. see my answer. -

don't use your own homebrew abs macro, it evaluates its argument twice. The C library has fabs for that. This usually a builtin, so the performance is the same but it is safe. -

4 Respuestas

Cambiando esta línea:

                a_sqrt = a_sqrt - ((a_sqrt*a_sqrt)-(x)/(2.0*a_sqrt));

a

                a_sqrt = a_sqrt - ((a_sqrt*a_sqrt - x)/(2.0*a_sqrt));

funciona para mi.

contestado el 03 de mayo de 12 a las 17:05

it worked but this doesn't follow the newton's method strictly - user1372984

it's approximately the bisection method - user1372984

Are you sure? It works for all integers from 0 to 100. Check the equations for Newton's method again. - fferen

it works but it is not the newton's method. the newton's method is x = x - f(x)/f'(x) thank you very much! i think C has its own precision problem, when i used the inbuilt function in the math.h library i got the same result. - user1372984

Try to use a bigger epsilon, maybe python uses doubles instead of floats.

contestado el 03 de mayo de 12 a las 17:05

Indeed. Epsilon for float should be more like 0.0000001 (7 decimal places) - Dr. Andrew Burnett-Thompson

double mysqrt(double x){
    double eps=pow(10,-10);
    double x0 = 0.0;
    double x1 = x/2.0;
    while(fabs(x1 - x0)>eps){
        x0 = x1;
        x1 = x0 + (x - x0*x0)/x0/ 2.0;
    }
    return x1;
}

expansión macro
abs((a_sqrt*a_sqrt)-(x))
expansión (((a_sqrt*a_sqrt)-(x))>0 ? (a_sqrt*a_sqrt)-(x): -(a_sqrt*a_sqrt)-(x))
NG: -(a_sqrt*a_sqrt)-(x)

abs((a_sqrt*a_sqrt- x))
expansión (((a_sqrt*a_sqrt- x))>0 ? (a_sqrt*a_sqrt- x): -(a_sqrt*a_sqrt- x))

volver a escribir
#define abs(a) ((a)>0 ? a: -a)
a
#define abs(a) ((a)>0 ? a: -(a))

contestado el 03 de mayo de 12 a las 18:05

This is one of the rare cases where using double actually makes sense. Note that the precision of float is significantly lower than eps_sqrt:

[mic@mic-nb tmp]$ cat tmp2.c
#include <stdio.h>
#include <math.h>

int main() {
    double a = sqrtl(2.0);
    printf("%1.20f\n", a - (float) a);
}
[mic@mic-nb tmp]$ gcc tmp2.c; ./a.out
0.00000002420323430563
vs. your value of:
0.00000000000001

So your program will, in most cases, never terminate.

contestado el 03 de mayo de 12 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.