Найти n-й корень всех чисел в интервале

У меня есть программа, которая должна печатать идеальные квадратные корни всех целых чисел в интервале. Теперь я хочу сделать это для n-root.

Вот что я сделал, но я застрял на 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;
}

2 ответа

Решение

Вы можете решить это в противоположном направлении. Вместо того, чтобы брать n-й корень каждого значения в интервале, чтобы увидеть, является ли n-й корень целым числом, вместо этого возьмите n-ный корень из границ интервала и перейдите к корням:

// 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;
}

Дополнительный тест внутри for Цикл должен обрабатывать случаи, когда min или же max приземлиться прямо на корень или просто в сторону корня.

Вы можете удалить тест и вычисление из цикла, признав, что raised нужен только на границах цикла. Эта версия, хотя и выглядит несколько сложнее, реализует это наблюдение:

// 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;

Если вы действительно беспокоитесь о производительности (а я подозреваю, что вы не в этом случае), вы можете заменить int( pow( ..., p ) ) с кодом, который полностью вычисляет n-ю степень с целочисленной арифметикой. Это похоже на излишество.

Точный тест на равенство для плавающих чисел может работать не так, как вы ожидаете. Лучше сравнить с небольшим числом:

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

Даже в этом случае вам не гарантируется получение правильных результатов для всех значений min, max и p. Все зависит от этого небольшого числа и точности представляемых вами чисел. Вы можете рассмотреть более длинные плавающие типы, такие как "double" и "long double".

Другие вопросы по тегам