2

I am trying to implement my own square root function which gives square root's integral part only e.g. square root of 3 = 1.

I saw the method here and tried to implement the method

 int mySqrt(int x)
 {
    int n = x;
    x = pow(2, ceil(log(n) / log(2)) / 2);
    int y=0;

    while (y < x)
    {
        y = (x + n / x) / 2;
        x = y;
    }

    return x;

}

The above method fails for input 8. Also, I don't get why it should work.

Also, I tried the method here

int mySqrt(int x)
{

    if (x == 0) return 0;
    int x0 = pow(2, (log(x) / log(2))/2) ;
    int y = x0;
    int diff = 10;

    while (diff>0)
    {
        x0 = (x0 + x / x0) / 2; diff = y - x0;
        y = x0;
        if (diff<0) diff = diff * (-1); 

    }

    return x0;

}

In this second way, for input 3 the loop continues ... indefinitely (x0 toggles between 1 and 2).

I am aware that both are essentially versions of Netwon's method but I can't figure out why they fail in certain cases and how could I make them work for all cases. I guess i have the correct logic in implementation. I debugged my code but still I can't find a way to make it work.

Community
  • 1
  • 1
adrian008
  • 395
  • 6
  • 17
  • 3
    C++ **IS NOT** C nor Java. – Luiggi Mendoza Jul 18 '15 at 16:54
  • @LuiggiMendoza I guess the logic will be same so I put the tags so that more people could find the question. – adrian008 Jul 18 '15 at 16:55
  • Other people that may understand Java and C but maybe not C++. I can understand the basics of C and C++, but please use the relevant and proper tags only. – Luiggi Mendoza Jul 18 '15 at 16:56
  • @LuiggiMendoza There is not much syntax. I put the language agnostic tag because I feel this is more of a programmiing thing. – adrian008 Jul 18 '15 at 16:57
  • 3
    You are storing the results in integer variables, what do you expect to happen here? – shuttle87 Jul 18 '15 at 16:57
  • @shuttle87 I am using only integral calculations. And it can be done using only inetgral calculations since i have to find only the integral part. – adrian008 Jul 18 '15 at 16:59
  • 1
    If I were you, I would debug the code or print the values of the result of each member of your operation e.g. `cout << log(n);` – Luiggi Mendoza Jul 18 '15 at 16:59
  • @LuiggiMendoza I did that. I debugged and I pointed the specific numbers where it fails and the reason it fails. I gave the links, I showed what I did.. – adrian008 Jul 18 '15 at 16:59
  • 1
    @adrian008 Neither `std::pow` not `std::log` nor `std::ceil` operate on integers. They all work in terms of floating point math, with all the inaccuracy (especially with truncating floating point - integer conversions) this implies.. – Baum mit Augen Jul 18 '15 at 17:00
  • 1
    @adrian008, newtons method assumes that you are operating on the domain of the real numbers, not on integers. The convergence of the algorithm is determined for the real numbers case on continuous functions, there's no guarantee however that an integral solution will converge. Additionally all the methods in the links are using floating point numbers as approximations of the reals, they aren't using integers. This means that the algorithm may not converge if you are implementing it in a naive way. – shuttle87 Jul 18 '15 at 17:02
  • @BaummitAugen could you once take a look at the links, I just implemented the well accepted answers on SO. If you could say what I am doing wrong it would be great, but ceil and log are not the problem, If you see the algo they are just involved in the initial assumption whicg might just be anything. – adrian008 Jul 18 '15 at 17:02
  • @shuttle87 yes, it is not converging for input 3, if you could say what should I do to my implementation to guarantee convegence it would be great. – adrian008 Jul 18 '15 at 17:03
  • 5
    You already have three comments on the same subject: you're storing the data in `int` when most of the operations return `float` or `double`. That's the whole problem. – Luiggi Mendoza Jul 18 '15 at 17:04
  • @LuiggiMendoza Is there a way to do using only integral calculations ? I have to find the integral part of the root only. Thanks. – adrian008 Jul 18 '15 at 17:12
  • Well... just do all the operations using floating point decimal variables, and in the end return `ceil(result)`. – Luiggi Mendoza Jul 18 '15 at 17:13
  • @LuiggiMendoza I changed all to float, still not working this time 2147395599 fails. – adrian008 Jul 18 '15 at 17:17
  • @LuiggiMendoza Also why ceil ? – adrian008 Jul 18 '15 at 17:18
  • `pow(2, ceil(log(n) / log(2)) / 2);` is very inefficient. Powers of 2 should be get by `1 << n` instead of `pow` which may be hundreds of times slower. There is also a [`log2`](http://en.cppreference.com/w/c/numeric/math/log2) function in C for getting log base 2 which is more correct and faster than your way, but since you want the integer value, it can be much more quickly calculated by [various ways](https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious) – phuclv Jul 18 '15 at 17:22
  • "It's not working" "It fails" This is not a scientific way to describe a problem. – Lightness Races in Orbit Jul 18 '15 at 17:46
  • @LightnessRacesinOrbit i even mentioned the inputs. – adrian008 Jul 18 '15 at 17:48
  • @LuiggiMendoza Thanks for your help but the problem was indeed solved using only integral calculations, and I think it highlighted an important point. – adrian008 Jul 18 '15 at 17:53

2 Answers2

1

This one works for me:

uintmax_t zsqrt(uintmax_t x)
{
    if(x==0) return 0;
    uintmax_t yn = x; // The 'next' estimate
    uintmax_t y = 0; // The result
    uintmax_t yp; // The previous estimate
    do{
        yp = y;
        y = yn;
        yn = (y + x/y) >> 1; // Newton step
    }while(yn ^ yp); // (yn != yp) shortcut for dumb compilers
    return y;
}

returns floor(sqrt(x))

Instead of testing for 0 with a single estimate, test with 2 estimates.

When I was writing this, I noticed the result estimate would sometimes oscillate. This is because, if the exact result is a fraction, the algorithm could only jump between the two nearest values. So, terminating when the next estimate is the same as the previous will prevent an infinite loop.

adrian008
  • 395
  • 6
  • 17
defube
  • 2,345
  • 1
  • 20
  • 30
0

Try this

int n,i;//n is the input number
 i=0;
 while(i<=n)
 {
    if((i*i)==n)
    {
        cout<<"The number has exact root : "<<i<<endl;
    }
    else if((i*i)>n)
    {
        cout<<"The integer part is "<<(i-1)<<endl;
    }
    i++;
 }

Hope this helps.

Aditya Kiran
  • 251
  • 1
  • 4
  • 12