user4118393
user4118393

Reputation:

Perfect squares in a given range: abnormal execution of loops

Program number 1: In a given range a and b where a<=b, I want to find whether a number is a perfect quare, if yes then print its root. Therefore, I wrote the following code:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
float squaredroot(int n) {
float low = 0.0, mid;
float high = (float)n+1;
while ((high-low) > 0.00001) {
    mid = (low+high) / 2;
    if (mid*mid < n) {
        low = mid;
    }
    else {
        high = mid;
    }
}
return low;
}

int main() {
int a,b,i=0; cin>>a>>b;
float roo=0.0;
for(i=a;i<=b;i++){
roo=squaredroot(i);
    if(floor(roo)==roo){
        cout<<roo<<endl;
    }
}
return 0;
}

For the given input 1 5 the output should be 2. But, the above program is not printing any value.


Nevertheless, when I tried running another program using the same base concept as Program number 1, that's mentioned above, It was executed perfectly. The task for the following program is to check whether the input is a perfect square or not. If yes, then print the root of the number, else print "Not a perfect square!". Here is the code for the Program number 2:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
float squaredroot(int n) {
float low = 0.0, mid;
float high = (float)n+1;
while ((high-low) > 0.00001) {
    mid = (low+high) / 2;
    if (mid*mid < n) {
        low = mid;
    }
    else {
        high = mid;
    }
}
return low;
}

int main() {
int a; cin>>a;
float roo=0.0;
roo=squaredroot(a);
if(floor(roo)==roo){
    cout<<roo<<endl;
}
else{
    cout<<"Not a perfect square!"<<endl;
}
return 0;
}

I am unable to find the mistake in the first program. Please help.

Upvotes: 6

Views: 334

Answers (2)

Carlos
Carlos

Reputation: 6021

Instead of messing about with the square root function, consider this:

  • Consecutive squares are separated by succeeding odd numbers.
  • It's pretty darned fast to add some integers. Also you are skipping more and more numbers each time.
  • Square root takes you to floats. This keeps the problem in integers, where it belongs.

So, to solve your problem elegantly, just do this:

#include <iostream>

using std::cout;

void print_perfect_square( int start, int end ) {
    int x = 0, nthOdd = 1;

    while ( x <= end ) {
        if ( x >= start ) {
            cout << x << " is a square and its root is "
                << nthOdd - 1  << '\n';
        }
        x += 2*nthOdd - 1;
        ++nthOdd;
    }
}

int main() {
    // it should find 9 and 16
    print_perfect_square(6,17);
    cout << '\n';
    // it sholuld skip negatives
    print_perfect_square(-10,5);
    cout << '\n';
    // it should print 25,36...
    print_perfect_square(20,100);
    return 0;
}

Upvotes: 3

Adi Levin
Adi Levin

Reputation: 5243

As Gyro Gearloose said, the problem is that squaredroot(4) returns 1.99999809, so floor(roo)!=roo. One way to fix this is to change the condition (floor(roo)==roo) to (fabs(roo - floor(roo+0.5)) < 0.00001). Notice that I'm using the same 0.00001 from the function squaredroot.

Upvotes: 2

Related Questions