Содержит ли ряд целых чисел, по крайней мере, один идеальный квадрат?

StackOverflow https://stackoverflow.com/questions/3140562

Вопрос

Учитывая два целых числа a а также b, есть эффективный способ проверить, есть ли другое целое число n Такое это a ≤ n2 < b?

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

Несмотря на то что Тестирование того, является ли отдельное целое число идеальным квадратом, быстрее, чем вычисление квадратного корня, Диапазон может быть большой, и я бы также предпочел, чтобы избежать выполнения этого теста на каждый номер в пределах диапазона.

Примеры:

  • intervalContainsSquare(2, 3) => false.
  • intervalContainsSquare(5, 9) => false (Примечание: 9 находится за пределами этого интервала)
  • intervalContainsSquare(9, 9) => false (этот интервал пуст)
  • intervalContainsSquare(4, 9) => True (4 находится внутри этого интервала)
  • intervalContainsSquare(5, 16) => True (9 находится внутри этого интервала)
  • intervalContainsSquare(1, 10) => True (1, 4 и 9 все в этом интервале)
Это было полезно?

Решение

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

Аналогично для этой проблемы вы можете сделать предварительное произведение, чтобы определить, что SQRT (B) -SQRT (A)> = 1, который затем означает, что A и B достаточно далеко друг от друга, что между ними должна быть квадрат. С какой-то алгебре это неравенство эквивалентно условию, которое (Ba-1) ^ 2> = 4 * a, или если вы хотите его в более симметричной форме, что (ab) ^ 2 + 1> = 2 * (A + б). Таким образом, эта предварительно проведена без квадратных корней, только с одним целочисленным продуктом и некоторыми дополнениями и вычитаниями.

Если A и B почти точно так же, то вы все равно можете использовать хитрость смотреть бинарные цифры низкого порядка как предварительное способность, чтобы знать, что между ними нет квадрата. Но они должны быть настолько близко друг к другу, что это предварительное обрезание не стоят этого.

Если эти предварительные организации неубедительны, то я не могу думать ни о чем другом, кроме решения всех остальных, <= Ceil (SQRT (A)) ^ 2 <b.


Поскольку возник вопрос о том, чтобы сделать алгебру правильно:

sqrt(b)-sqrt(a) >= 1
sqrt(b) >= 1+sqrt(a)
b >= 1+2*sqrt(a)+a
b-a-1 >= 2*sqrt(a)
(b-a-1)^2 >= 4*a

Также: в целом, когда A - это большое число, вы бы вычисляете SQRT (A) с методом Ньютона или с таблицей поиска, за которой следует несколько шагов метода Newton. В принципе быстрее вычислить CEIL (SQRT (A)), чем SQRT (A), поскольку арифметика с плавающей точкой может быть упрощена до целочисленного арифметика, и поскольку вам не нужно столько шагов метода Ньютона, чтобы зажать высокую точность Ты просто собираешься выбросить. Но на практике функция численной библиотеки может быть намного быстрее, если она использует квадратные корни, реализованные в микрокоде. Если по какой-либо причине у вас нет этого микрокода, чтобы помочь вам, то это возможно, стоит того, чтобы поручить код CEIL (SQRT (A)). Возможно, самый интересный случай будет, если A и B неограниченные целые числа (например, тысяча цифр). Но для обычных целых чисел на обычном не устаревшем компьютере, вы не можете победить ФПУ.

Другие советы

Получите квадратный корень нижнего числа. Если это целое число, то вы сделаете. В противном случае вокруг и квадрат числа. Если это меньше, чем B, то это правда.

Вам нужно только вычислить один квадратный корень таким образом.

Чтобы избежать проблемы, когда A равен B, вы должны проверить это первым. Как этот случай всегда ложно.

Если вы будете принимать расчет двух квадратных корней, из-за его монотонности у вас есть это неравенство, которое эквивалентно вашему началу:

sqrt(a) <= n < sqrt(b)

Таким образом, если floor(sqrt(a)) != floor(sqrt(b)), floor(sqrt(b)) - 1 гарантированно будет таким n.

  1. Получите квадратный корень нижнего числа и закруглить его
  2. получить квадратный корень из более высокого числа и закруглить его
  3. Если 1 ниже или равно 2, будет идеальный квадрат

Найти неотъемлемую часть SQRT (A) и SQRT (B), скажем, SA и SB.

Если SA.2 = a, затем вывод да.

Если SB.2 = b и sa = sb-1, затем вывод no.

Если SA <SB выход да.

Еще не вывод нет.

Вы можете оптимизировать вышеизложенное, чтобы избавиться от вычисления SQRT (B) (аналогично ответу Jdunkerly).

Или вы хотели избежать вычислительных квадратных корней A и B тоже?


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

Вы начинаете с угадания для n, n = 1 и вычислить n2

Рассмотрим, если A <= N <B, вы можете остановиться.

Если n <a <b, удваиваете ваше предположение n. Если A <B <N, вы делаете его близко к среднему текущему + предыдущее предположение.

Это будет o (logb) время.

В дополнение к хорошему решению Jdunkerley (+1), может быть возможное улучшение, которое необходимо проверить и использовать целочисленные квадратные корни рассчитать целочисленные квадратные корни

Почему вы надеетесь избежать квадратных корней полностью? Еще до того, как вы доберетесь до самого эффективного способа решения этого, вы видели методы, которые требуют только для 2 квадратных корней. Это сделано в O (1) время, поэтому мне кажется, что любое улучшение, которое вы могли бы надеяться заставить потребовать больше времени, чтобы подумать о том, что он когда-либо сэкономит вам вычислительное время. Я ошибся?

Один из способов - использовать метод Ньютона, чтобы найти целочисленный квадратный корень для b. Отказ Тогда вы можете проверить, падает ли этот номер в диапазоне. Я сомневаюсь, что это быстрее, чем просто звонить квадратной корневой функции, но это, безусловно, интереснее:

int main( int argc, char* argv[] )
{
    int a, b;
    double xk=0, xk1;
    int root;
    int iter=0;
    a = atoi( argv[1] );
    b = atoi( argv[2] );

    xk1 = b / 32 + 1;  // +1 to ensure > 0
    xk1 = b;
    while( fabs( xk1 - xk ) >= .5 ) {
        xk = xk1;
        xk1 = ( xk + b / xk ) / 2.;
        printf( "%d) xk = %f\n", ++iter, xk1 );
    }

    root = (int)xk1;

    // If b is a perfect square, then this finds that root, so it also
    // needs to check if (n-1)^2 falls in the range.
    // And this does a lot more multiplications than it needs
    if ( root*root >= a && root*root < b ||
         (root-1)*(root-1) >= a && (root-1)*(root-1) < b )
        printf( "Contains perfect square\n" );
    else
        printf( "Does not contain perfect square\n" );

    return 1;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top