贝利信息

c++中如何判断一个数是否为完全平方数_c++数学算法实现【详解】

日期:2026-01-16 00:00 / 作者:尼克
用sqrt判断需防浮点误差,推荐先转double取整再验证root²和(root+1)²;更稳妥用llround;或采用二分查找,以mid

sqrt 判断是否为完全平方数,但要注意浮点误差

直接调用 sqrt 然后取整再平方验证,是最直观的做法,但 double 类型在大整数(比如超过 2^53)时无法精确表示所有整数,会导致误判。

实操建议:

bool isPerfectSquare(long long x) {
    if (x < 0) return false;
    long long r = std::llround(std::sqrt(static_cast(x)));
    return r >= 0 && r * r == x;
}

不用浮点运算:二分查找法判断完全平方数

适用于不允许浮点、或需要 100% 整数精度的场景(如竞赛、嵌入式、大数处理)。时间复杂度 O(log n),无精度风险。

关键点:

bool isPerfectSquare(long long x) {
    if (x < 0) return false;
    if (x <= 1) return true;
    long long left = 1, right = x / 2; // sqrt(x) <= x/2 for x >= 4
    while (left <= right) {
        long long mid = left + (right - left) / 2;
        if (mid == x / mid && x % mid == 0) return true;
        if (mid < x / mid) left = mid + 1;
        else right = mid - 1;
    }
    return false;
}

位运算 + 牛顿迭代:高效且适合高频调用

牛顿迭代收敛极快(通常 5~6 步内收敛到整数根),配合初始值优化(如用 bit length 快速估算),比二分更快,也避免浮点误差——只要全程用整数除法。

注意事项:

bool isPerfectSquare(long long x) {
    if (x < 0) return false;
    if (x <= 1) return true;
    long long r = x;
    while (r > x / r) r = (r + x / r) / 2; // integer Newton
    return r * r == x || (r + 1) * (r + 1) == x || (r - 1) * (r - 1) == x;
}

负数、零、大整数的边界行为必须显式处理

sqrt 对负数返回 NaN,而整数运算中负数永远不是完全平方数;01 是合法完全平方数;LLONG_MAX 这类值传给 sqrt 会丢失精度,必须靠整数方法兜底。

常见翻车点:

真正稳定的做法,是把整数二分作为 fallback,只在确认输入范围安全时才用 sqrt 加速。精度和边界,从来不是“理论上没问题”就能绕开的。