完美的Java代码来判断一个双精度是不是一个完美的正方形?

完美的Java代码来判断一个双精度是不是一个完美的正方形?,java,numbers,Java,Numbers,我想确定一个数字(双精度)是否是一个完美的正方形。我使用了下面的代码,但它在许多输入中失败 private static boolean isSquare(double i) { double s = Math.sqrt(i); return ((s*s) == i); } 当s得出科学形式的结果时,代码失败。例如,当s为2.719601835756618E9时,代码不会尝试测试数字的平方根是否为整数。任何非负实数都是其他实数的平方;代码的结果完全取决于

我想确定一个数字(双精度)是否是一个完美的正方形。我使用了下面的代码,但它在许多输入中失败

private static boolean isSquare(double i) {
        double s = Math.sqrt(i);
        return ((s*s) == i);
    }

s
得出科学形式的结果时,代码失败。例如,当
s
2.719601835756618E9
时,代码不会尝试测试数字的平方根是否为整数。任何非负实数都是其他实数的平方;代码的结果完全取决于浮点舍入行为

测试平方根是否为整数:

if (Double.isInfinite(i)) {
    return false;
}
sqrt = Math.sqrt(i);
return sqrt == Math.floor(sqrt) && sqrt*sqrt == i;
sqrt*sqrt==i
检查应能捕捉到某些情况,即非常接近平方的数字有一个平方根,其最近的
double
近似值为整数。我没有对此进行测试,也不保证其正确性;如果你希望你的软件是健壮的,不要只是从答案中复制代码


更新:发现一个失败的边缘案例。如果整数双精度具有足够长的最大奇数因子,以致于该平方不可表示,则将该平方的最接近的双精度近似值馈送到此代码将导致误报。目前我能想到的最好的解决办法是直接检查平方根的有效位,以确定表示平方需要多少位精度。不过,谁知道我还遗漏了什么?

我知道这个问题很老,但我还是会发布我的解决方案:

return Math.sqrt(i) % 1d == 0;

只需检查
sqrt
是否有小数。

静态布尔值checkPerfectSquare(双x)
{


你说的“指数形式”是什么意思?而“通常”是失败的?对于
double,没有“指数形式”这样的东西。
对于
double,
的字符串表示有科学的符号,例如由
double.toString()确定的.
您的问题缺乏精确性和细节。请修改。我已编辑了我的问题,如果需要添加更多内容,请发表意见,否则您可以给我一个代码,它将完美地确定任何双精度值是否为完美的平方。可能由于舍入问题,问题来自使用双精度,请尝试使用BigDecimal-instead@GeorgeTomlinson:用
i=Math.nextAfter(1e44,1e55)
试试。它通过
i!=Math.floor(i)
sqrt==Math.floor(sqrt)
检查,但它不是一个完美的平方。最后一个检查捕捉到了它。哦,对了。为什么需要if语句?整数的平方不可能是整数吗?+1表示其余部分和您的注释。请参考此项,看看您的答案为什么不起作用。我已经提到了所有的测试用例。@GeorgeTomlinson:我不知道墨迹是需要的。我把它扔进了一个半心半意的过早优化中。它甚至可能没有帮助。就像我说的,如果你想让你的软件变得健壮,盲目复制它不是一个好主意。@Ramswaroop:你的函数仍然不测试平方根是否是整数。它只测试原始数字是否是整数。请注意,
sqrt==Math.floor(sqrt)
check.Receive一个“-1”可能很有用,因为我可以从错误中吸取教训,但没有理由地接受它——它毫无意义。
// finding the square root of given number 
double sq = Math.sqrt(x); 

/* Math.floor() returns closest integer value, for
 * example Math.floor of 984.1 is 984, so if the value
 * of sq is non integer than the below expression would
 * be non-zero.
 */
return ((sq - Math.floor(sq)) == 0); 
}