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)) |