Algorithm 什么';判断输入是否为完美正方形的好算法是什么?

Algorithm 什么';判断输入是否为完美正方形的好算法是什么?,algorithm,math,perfect-square,Algorithm,Math,Perfect Square,可能重复: 用什么方法来判断一个数字是否是一个数字? bool IsPerfectSquare(长输入) { //待办事项 } 我用的是C#,但这是语言不可知论 清晰和简单的额外积分(这不是代码高尔夫) 编辑:这比我想象的要复杂得多!事实证明,双精度问题有两种表现形式。首先,数学。Sqrt需要一个不能精确容纳长时间的双精度(谢谢Jon) 第二,当你有一个巨大的、近乎完美的正方形时,一个双精度的精度会损失很小的值(.000…00001)。e、 例如,我的实现没有通过Math.Pow(10,

可能重复:

用什么方法来判断一个数字是否是一个数字?

bool IsPerfectSquare(长输入)
{
//待办事项
}
我用的是C#,但这是语言不可知论

清晰和简单的额外积分(这不是代码高尔夫)


编辑:这比我想象的要复杂得多!事实证明,双精度问题有两种表现形式。首先,数学。Sqrt需要一个不能精确容纳长时间的双精度(谢谢Jon)

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

bool IsPerfectSquare(长输入)
{
long closestRoot=(long)Math.Sqrt(输入);
返回输入==closestRoot*closestRoot;
}
这可以避免一些只检查“平方根是整数”的问题,但可能不是全部。你可能需要变得更时髦一点:

bool IsPerfectSquare(长输入)
{
双根=Math.Sqrt(输入);
long rootBits=位转换器。doubleToInt64位(根);
long lowerBound=(长)位转换器。Int64BitsToDouble(rootBits-1);
长上限=(长)位转换器。Int64BitsToDouble(rootBits+1);
for(长候选=低边界;候选<代码>布尔IsPerfectSquare(长输入)
{
长平方根=(长)数学.Sqrt(输入);
返回((平方根*平方根)=输入);
}

在Common Lisp中,我使用以下命令:

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

我喜欢在修正到更可靠的解决方案之前我得到的投票数;)哥们,你是jon skeet。@jon:我正在考虑取消我的投票。他要求清楚和简单。:)我认为准确性很重要。否则我会选择“保证随机”回答:)你不需要防弹的解决方案。经过了详尽的测试。有一个非常类似的问题。请参考以获得一个非常好的答案。对于你选择的解决方案,不要忘记预先快速检查消极性。是的,我有一个在那里,但为了简洁起见删除了它。谢谢你指出它,尽管你也可以继续对于整数平方根的“lsqrt”方法,Michael,蜥蜴比尔提出了一个很好的观点,那就是这只是一个类似的问题,而不是完全重复的问题。我认为这个问题不需要封闭。此外,完美平方的问题在实际应用中要比它看起来复杂得多,这里的答案对我们有很大的帮助看看,我应该补充一点,Common Lisp有一个“完整”的数字堆栈,所以这只适用于任何非负整数(当然受工作内存的限制)。在SBCL上,
square
应该是
expt
(defun perfect-square-p(n)(=(expt(isqrt n)2)n))
@BenSima:实际上,由于标准中没有定义
square
,因此您需要在任何实现中定义(或替换)它。我编辑答案是为了不产生这种依赖性。