web-dev-qa-db-ja.com

入力が完全な正方形であるかどうかを判断するのに適したアルゴリズムは何ですか?

可能性のある複製:
整数の平方根が整数かどうかを判断する最も速い方法

数値が 完全な正方形 であるかどうかを確認する方法は何ですか?

bool IsPerfectSquare(long input)
{
   // TODO
}

私はC#を使用していますが、これは言語に依存しません。

明快さと単純さのためのボーナスポイント(これはコードゴルフを意図したものではありません)。


編集:これは予想よりもはるかに複雑になりました!倍精度の問題はいくつかの方法で明らかになります。まず、Math.Sqrtはlongを正確に保持できないdoubleを取ります(Jonに感謝)。

第二に、巨大で完全に近い正方形がある場合、倍精度は小さな値(.000 ... 00001)を失います。たとえば、私の実装はMath.Pow(10,18)+1のこのテストに失敗しました(私の報告ではtrueでした)。

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

これは、「平方根が整数か」をチェックするだけの問題のsomeから逃れるかもしれませんが、すべてではないかもしれません。あなたは潜在的に少しファンキーになる必要があります:

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、そして本当に大きな値以外には不要ですが、私はそれを考えますshould work ...

116
Jon Skeet
bool IsPerfectSquare(long input)
{
    long SquareRoot = (long) Math.Sqrt(input);
    return ((SquareRoot * SquareRoot) == input);
}
12
Treb

Common LISPでは、次を使用します。

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