关于数学:确定输入是否是完美正方形的好算法是什么?

What's a good algorithm to determine if an input is a perfect square?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Fastest way to determine if an integer's square root is an integer

怎样才能知道一个数是否是一个完美的平方?

1
2
3
4
bool IsPerfectSquare(long input)
{
   // TODO
}

我用的是C,但这是语言不可知论。

为了清晰和简单的奖励积分(这不是代码高尔夫)。

编辑:这比我想象的要复杂得多!结果表明,双精度的问题有两种表现方式。首先,math.sqrt需要一个不能精确保持长时间的双精度(谢谢jon)。

第二,当你有一个巨大的,接近完美的正方形时,一个双精度数的精度会损失很小的值(.000…00001)。例如,我的实现在Math.Pow(10,18)+1(我的报告为真)的测试中失败。


1
2
3
4
5
bool IsPerfectSquare(long input)
{
    long closestRoot = (long) Math.Sqrt(input);
    return input == closestRoot * closestRoot;
}

这可以避免一些只检查"平方根是整数"的问题,但可能不是全部。你可能需要变得更有趣一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}

恶心,除了真正的大价值之外什么都不需要,但我认为它应该起作用…


1
2
3
4
5
bool IsPerfectSquare(long input)
{
    long SquareRoot = (long) Math.Sqrt(input);
    return ((SquareRoot * SquareRoot) == input);
}


在普通的Lisp中,我使用以下方法:

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