0
#include <iostream>

float calculating_root(float N, float root_N, float increment)
{
    int safety=1;
    while(safety==1)
    {
        if (N == (root_N*root_N))
        {
            safety=0;
            return root_N;  
        }
        else if(N<((root_N+increment)*(root_N+increment)))
        {
            safety=0;
            return calculating_root(N,root_N, increment*0.1);
        }
        root_N=root_N+increment;
    }
}

int main()
{
    float N, root_N=0.0, increment=1000.0;

    scanf("%f",&N);

    float x = calculating_root(N, root_N, increment);

    printf("\n%g\n",x);

    return 0;
}

I've been thinking about it for such a long time. I guess I don't have other ideas, everything seems perfect? Does anyone sees a mistake?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Kamila
  • 69
  • 8
  • 1
    Welcome to Stack Overflow. What happens when you try to run the code? How is that different from what is supposed to happen? What happened when you [tried to solve the problem yourself](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) (which is [expected](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users))? Please also read [ask]. – Karl Knechtel Jul 28 '21 at 09:47
  • 3
    You can get rid of `safety`: `while (safety==1)` -> `while (true)` – Jarod42 Jul 28 '21 at 09:47
  • 2
    Floating comparisons such as `N == (root_N * root_N)` is really fragile. – Jarod42 Jul 28 '21 at 09:49
  • 2
    Can't reproduce (I tried different input numbers and always got a good square root). But the `==` operator on `float` variables can often be the source of failure. – Adrian Mole Jul 28 '21 at 09:49
  • That's what I was thinking about. But how can I do something about ==? And I noticed that also the < operator isn't really working. When comparing the same numbers it returns true... – Kamila Jul 28 '21 at 09:56
  • @AdrianMole: I have infinite loop for `N == 6.f` or `N == 0.01f`. – Jarod42 Jul 28 '21 at 09:59
  • 1
    Related to [is-floating-point-math-broken](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Jarod42 Jul 28 '21 at 10:00
  • 3
    why do you say it would be C? `` is not C, though you arent using it but instead miss other includes for the C functions you are using. Please only tag the language you are actually using to compile the code. When you compile it as C++ then it is C++ – 463035818_is_not_an_ai Jul 28 '21 at 10:09

1 Answers1

3

Using == for comparing floating point numbers that you calculated is not advised. Especially in this case N might actually be a number that is not representable by any float a such that a*a == N.

so instead of

N == (root_N*root_N)

try to use something like

fabs(N-(root_N*root_N)) < epsilon

Where epsilon is your acceptable rounding error. You could choose something like const float epsilon = 0.000001f. I think in this case you might need something above the machine epsilon, because you're potentially accumulating the error.

You could also improve precision somewhat by using double instead of float. That will however not replace the need for the epsilon, only allow you to choose a lower epsilon.

PeterT
  • 7,981
  • 1
  • 26
  • 34
  • Note also, that for big number, the `increment` will be to small compared to `N_root`. It that case, `N_root + increment` will be equal to`N_root` and the loop will be infinite... – Mathieu Jul 28 '21 at 10:08
  • Thank you very much! I used double and this epsilon thing and it's working PERFECTLY ;) Also I made an additional if statement at the very beginning, so if the increment is too small, the function returns root_N – Kamila Jul 28 '21 at 17:35