【问题标题】:What's a good algorithm to determine if an input is a perfect square? [duplicate]确定输入是否是完美正方形的好算法是什么? [复制]
【发布时间】:2010-09-25 12:34:13
【问题描述】:

可能重复:
Fastest way to determine if an integer's square root is an integer

查看数字是否为perfect square 的方法是什么?

bool IsPerfectSquare(long input)
{
   // TODO
}

我使用的是 C#,但这与语言无关。

为清晰和简单加分(这并不意味着代码高尔夫)。


编辑:这比我预期的要复杂得多!事实证明,双精度的问题体现在几个方面。首先,Math.Sqrt 需要一个不能精确保持长的双精度(感谢乔恩)。

其次,当你有一个巨大的、近乎完美的正方形时,双精度将丢失小的值 (.000...00001)。例如,我的实现未通过 Math.Pow(10,18)+1 的此测试(我的报告为真)。

【问题讨论】:

  • 有一个非常相似的问题。请参考stackoverflow.com/questions/295579/… 以获得出色的答案。
  • 对于您选择的解决方案,不要忘记预先快速检查是否有负面影响。
  • 是的,我把它放在那里,但为简洁起见将其删除。感谢您指出这一点
  • 你也可以谷歌搜索用于整数平方根的 'lsqrt' 方法。
  • 迈克尔,蜥蜴比尔提出了一个很好的观点,即这只是一个类似的问题,而不是完全相同的问题。我认为这个问题不需要结束。此外,完全平方的问题实际上比看起来要复杂得多,这里的答案做出了很大的贡献。

标签: algorithm math perfect-square


【解决方案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;
}

令人讨厌,除了非常大的值之外,其他任何东西都是不必要的,但我认为它应该工作......

【讨论】:

  • 喜欢我在 将其更正为更安全的解决方案之前获得的赞成票数量;)
  • 老兄,你是乔恩·斯基特。
  • @Jon:我正在考虑撤销我的投票。他要求清晰简单。 :)
  • 我认为准确性很重要。否则我会选择“保证是随机的”回应:)
  • 不需要你的防弹解决方案。经过详尽测试和sort-of proven
【解决方案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))
    

    【讨论】:

    • 嘿。看看stackoverflow.com/a/343862/31615,我应该补充一点,Common Lisp 有一个“完整的”数字堆栈,所以这只适用于任何非负整数(当然,受工作内存的限制)。跨度>
    • 在 SBCL 上,square 应该是 expt: (defun perfect-square-p (n) (= (expt (isqrt n) 2) n))
    • @BenSima:实际上,由于标准中没有定义square,因此您需要在任何实现中定义(或替换)它。我编辑答案是为了不产生这种依赖。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 2020-10-03
    • 2019-02-22
    • 2022-08-23
    • 2015-07-05
    • 2020-11-27
    相关资源
    最近更新 更多