Проверьте, является ли одно целое число целым числом другого

Это вопрос : "Если заданы 2 целых числа x и y, проверьте, является ли x целочисленной степенью y" (например, для x = 8 и y = 2 ответ "истинно", а для x = 10 и y = 2 "false" ).

Очевидное решение:

int n = y; while(n < x) n *= y; return n == x

Теперь я думаю о том, как улучшить его.

Конечно, я могу проверить некоторые особые случаи: например. оба x и y должны быть либо нечетными, либо четными числами, то есть мы можем проверить младший значащий бит x и y. Однако я задаюсь вопросом, могу ли я улучшить сам алгоритм ядра.

Ответ 1

Вам нужно будет многократно разделить y на x. Когда вы получаете ненулевой остаток, вы знаете, что x не является целым числом y.

while (x%y == 0)  x = x / y
return x == 1

Это касается вашей нечетной/четной точки на первой итерации.

Ответ 2

Это означает log y (x) должно быть целое число. Не нужен цикл. в O (1) время

public class PowerTest {

    public static boolean isPower(int x, int y) {
        double d = Math.log(Math.abs(x)) / Math.log(Math.abs(y));

        if ((x > 0 && y > 0) || (x < 0 && y < 0)) {
            if (d == (int) d) {
                return true;
            } else {
                return false;
            }
        } else if (x > 0 && y < 0) {
            if ((int) d % 2 == 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        System.out.println(isPower(-32, -2));
        System.out.println(isPower(2, 8));
        System.out.println(isPower(8, 12));
        System.out.println(isPower(9, 9));
        System.out.println(isPower(-16, 2));
        System.out.println(isPower(-8, -2));
        System.out.println(isPower(16, -2));
        System.out.println(isPower(8, -2));
    }

}

Ответ 3

Здесь отображается показатель экспоненты в шагах O (log N):

#define MAX_POWERS 100

int is_power(unsigned long x, unsigned long y) {
  int i;
  unsigned long powers[MAX_POWERS];
  unsigned long last;
  last = powers[0] = y;

  for (i = 1; last < x; i++) {
    last *= last; // note that last * last can overflow here!
    powers[i] = last;
  }
  while (x >= y) {
    unsigned long top = powers[--i];
    if (x >= top) {
      unsigned long x1 = x / top;
      if (x1 * top != x) return 0;
      x = x1;
    }
  }
  return (x == 1);
}

Отрицательные числа не обрабатываются этим кодом, но это можно сделать легко с некоторым условным кодом, если i = 1

Ответ 4

Это выглядит довольно быстро для положительных чисел, поскольку он находит нижний и верхний пределы для желаемой мощности, а затем применяет двоичный поиск.

#include <iostream>
#include <cmath>
using namespace std;

//x is the dividend, y the divisor.
bool isIntegerPower(int x, int y)
{
    int low = 0, high;
    int exp = 1;
    int val = y;
    //Loop by changing exponent in the powers of 2 and
    //Find out low and high exponents between which the required exponent lies.
    while(1)
    {
        val = pow((double)y, exp);
        if(val == x)
            return true;
        else if(val > x)
            break;
        low = exp;
        exp = exp * 2;
        high = exp;
    }
    //Use binary search to find out the actual integer exponent if exists
    //Otherwise, return false as no integer power.
    int mid = (low + high)/2;
    while(low < high)
    {
        val = pow((double)y, mid);
        if(val > x)
        {
            high = mid-1;
        }
        else if(val == x)
        {
            return true;
        }
        else if(val < x)
        {
            low = mid+1;
        }
        mid = (low + high)/2;
    }
    return false;
}

int main()
{
    cout<<isIntegerPower(1024,2);
}

Ответ 5

Я бы выполнил такую ​​функцию:

bool IsWholeNumberPower(int x, int y)
{
    double power = log(x)/log(y);
    return floor(power) == power;
}

Это не требует проверки внутри дельта, как это обычно бывает при сравнении с плавающей запятой, так как мы проверяем целые числа.

Ответ 6

Во вторых, не делайте этого. Он не работает для отрицательных x и/или y. Обратите внимание, что все остальные ответы на основе log, представленные прямо сейчас, также разбиты точно так же.

Ниже приведено быстрое общее решение (в Java):

static boolean isPow(int x, int y) {
    int logyx = (int)(Math.log(x) / Math.log(y));
    return pow(y, logyx) == x || pow(y, logyx + 1) == x;
}

Где pow() - целочисленная функция экспоненции, такая как следующее в Java:

static int pow(int a, int b) {
    return (int)Math.pow(a, b);
}

(Это работает из-за следующей гарантии, предоставляемой Math.pow: "Если оба аргумента являются целыми числами, то результат точно равен математическому результату поднятия первого аргумента на мощность второго аргумента..." )

Причиной идти с логарифмами вместо повторного деления является производительность: в то время как журнал медленнее, чем деление, он медленнее с небольшим фиксированным кратным. В то же время он устраняет необходимость в цикле и поэтому дает вам алгоритм с постоянным временем. Забастовкa >

Ответ 7

В случаях, когда y равно 2, существует быстрый подход, который позволяет избежать необходимости в цикле. Этот подход можно распространить на случаи, когда y является некоторой большей степенью 2.

Если x - степень 2, двоичное представление x имеет один бит набора. Существует довольно простой алгоритм бит-возиться для подсчета битов в целое число в O (log n), где n - ширина бита целого числа. Многие процессоры также имеют специализированные инструкции, которые могут обрабатывать это как одну операцию, примерно так же быстро, как (например) целочисленное отрицание.

Однако для расширения подхода сначала нужно немного по-другому взглянуть на проверку одного бита. Сначала определите положение младшего значащего бита. Опять же, есть простой алгоритм бит-возиться, и у многих процессоров есть быстрые специализированные инструкции.

Если этот бит является единственным битом, тогда (1 << pos) == x. Преимущество здесь в том, что если вы тестируете мощность 4, вы можете протестировать для pos % 2 == 0 (один бит находится в четном положении). Тестируя для мощности любой мощности в два, вы можете проверить pos % (y >> 1) == 0.

В принципе, вы можете сделать что-то подобное для тестирования для полномочий 3 и степеней полномочий 3. Проблема в том, что вам понадобится машина, которая работает в базе 3, что маловероятно. Вы можете, конечно, проверить любое значение x, чтобы увидеть, имеет ли его представление в базе y одну ненулевую цифру, но вы будете делать больше работы, которую вы уже делаете. Вышеизложенное говорит о том, что компьютеры работают в двоичном формате.

Наверное, не стоит делать в реальном мире.

Ответ 8

    double a=8;
    double b=64;

    double n = Math.log(b)/Math.log(a);
    double e = Math.ceil(n);

    if((n/e) == 1){
        System.out.println("true");
    } else{
       System.out.println("false");
    }

Ответ 9

Предыдущие ответы верны, мне понравился Пол, отвечающий наилучшим образом. Это просто и чисто. Вот реализация Java, которую он предложил:

public static boolean isPowerOfaNumber(int baseOrg, int powerOrg) {
    double base = baseOrg;
    double power = powerOrg;

    while (base % power == 0)
        base = base / power;
    // return true if base is equal 1
    return base == 1;
}

Ответ 10

Если у вас есть доступ к наибольшей мощности y, которая может быть установлена ​​внутри требуемого типа данных, это действительно гладкий способ решения этой проблемы.

Допустим, для нашего случая y == 3. Итак, нам нужно проверить, является ли x степенью 3.

Учитывая, что нам нужно проверить, является ли целое число x степенью 3, начнем думать об этой проблеме с точки зрения того, какая информация уже имеется.

1162261467 - это наибольшая мощность 3, которая может вписываться в Java int.
1162261467 = 3^19 + 0

Данный x может быть выражен как [(a power of 3) + (some n)]. Я считаю, что достаточно элементарно доказать, что если n равно 0 (что происходит , если f x является степенью 3), 1162261467 % x = 0.

Итак, чтобы проверить, является ли заданное целое число x степенью трех, проверьте, если x > 0 && 1162261467 % x == 0.

Обобщая. Чтобы проверить, является ли заданное целое число x степенью заданного целого y, проверьте, является ли x > 0 && Y % x == 0: y наибольшая степень y, которая может вписываться в целочисленный тип данных.

Общая идея состоит в том, что если A - некоторая степень y, A может быть выражена как B/Ya, где a - некоторое целое число и A < B. Это следует за тем же принципом для A > B. Случай A = B является элементарным.

Ответ 11

Я нашел это решение //Check for If A может быть выражено как мощность двух целых чисел

    int isPower(int A)
    {
     int i,a;
     double p;
     if(A==1)
     return 1;
     for(int a=1; a<=sqrt(A);++a )
     {
         p=log(A)/log(a);
         if(p-int(p)<0.000000001)
         return 1;
     }
    return 0;
   }

binarycoder.org