Daniel
Daniel

Reputation: 39

Find n-th root of all numbers within an interval

I have a program which must print perfect square roots of all integer numbers within an interval. Now I want to do that for n-the root.

Here's what I've done, but I'm stuck at fmod.

#include <iostream>
#include <math.h>
using namespace std;

int nroot(int, int);

int main()
{

    int p, min, max,i;
    double q;

    cout << "enter min and max of the interval \n";
    cin >> min;
    cin >> max;
    cout << "\n Enter the n-th root \n";
    cin >> p;
    i = min;

    while (i <= max)
    {
        if (fmod((nroot(i, p)), 1.0) == 0)
        {
            cout << nroot(i, p);
        }
        i++;
    }
    return 0;
}

int nroot (int i, int p){

    float q;
    q = (pow(i, (1.0 / p)));

    return q;
}

Upvotes: 1

Views: 622

Answers (2)

Joe Z
Joe Z

Reputation: 17926

You may want to tackle this in the opposite direction. Rather than taking the nth root of every value in the interval to see if the nth root is an integer, instead take the nth root of the bounds of the interval, and step in terms of the roots:

// Assume 'min' and 'max' set as above in your original program.
// Assume 'p' holds which root we're taking (ie. p = 3 means cube root)
int min_root = int( floor( pow( min, 1. / p ) ) );
int max_root = int( ceil ( pow( max, 1. / p ) ) );

for (int root = min_root; root <= max_root; root++)
{
    int raised = int( pow( root, p ) );
    if (raised >= min && raised <= max)
        cout << root << endl;
}

The additional test inside the for loop is to handle cases where min or max land directly on a root, or just to the side of a root.

You can remove the test and computation from the loop by recognizing that raised is only needed at the boundaries of the loop. This version, while slightly more complex looking, implements that observation:

// Assume 'min' and 'max' set as above in your original program.
// Assume 'p' holds which root we're taking (ie. p = 3 means cube root)
int min_root = int( floor( pow( min, 1. / p ) ) );
int max_root = int( ceil ( pow( max, 1. / p ) ) );

if ( int( pow( min_root, p ) ) < min )
    min_root++;

if ( int( pow( max_root, p ) ) > max )
    max_root--;

for (int root = min_root; root <= max_root; root++)
    cout << root << endl;

If you're really concerned about performance (which I suspect you are not in this case), you can replace int( pow( ..., p ) ) with code that computes the nth power entirely with integer arithmetic. That seems like overkill, though.

Upvotes: 2

HEKTO
HEKTO

Reputation: 4191

Exact equality test for floating numbers might not work as you expect. It's better to compare with some small number:

float t = nroot(i, p);
if (fabs(t - rintf(t)) <= 0.00000001)
{
  cout << t << endl;
}

Even in this case you aren't guaranteed to get correct results for all values of min, max and p. All depends on this small number and precision you represent numbers. You might consider longer floating types like "double" and "long double".

Upvotes: 1

Related Questions