Подтвердить что ты не робот

Какой хороший алгоритм определить, является ли вход идеальным квадратом?

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

Какой способ увидеть, является ли число идеальным квадратом?

bool IsPerfectSquare(long input)
{
   // TODO
}

Я использую С#, но это агностик языка.

Бонусные очки для ясности и простоты (это не значит, что это кодовый гольф).


Изменить: Это намного сложнее, чем я ожидал! Оказывается, проблемы с двойной точностью проявляют себя несколькими способами. Во-первых, Math.Sqrt берет двойной, который не может точно удерживать длинный (спасибо Jon).

Во-вторых, двойная точность потеряет небольшие значения (.000... 00001), когда у вас будет огромный, почти идеальный квадрат. например, моя реализация не прошла этот тест для Math.Pow(10,18) +1 (мой сообщенный true).

4b9b3361

Ответ 1

bool IsPerfectSquare(long input)
{
    long closestRoot = (long) Math.Sqrt(input);
    return input == closestRoot * closestRoot;
}

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

bool IsPerfectSquare(long input)
{
    double root = Math.Sqrt(input);

    long rootBits = BitConverter.DoubleToInt64Bits(root);
    long lowerBound = (long) BitConverter.Int64BitsToDouble(rootBits-1);
    long upperBound = (long) BitConverter.Int64BitsToDouble(rootBits+1);

    for (long candidate = lowerBound; candidate <= upperBound; candidate++)
    {
         if (candidate * candidate == input)
         {
             return true;
         }
    }
    return false;
}

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

Ответ 2

bool IsPerfectSquare(long input)
{
    long SquareRoot = (long) Math.Sqrt(input);
    return ((SquareRoot * SquareRoot) == input);
}

Ответ 3

В Common Lisp я использую следующее:

(defun perfect-square-p (n)
  (= (expt (isqrt n) 2)
     n))