0

0

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

尼克

尼克

发布时间:2026-01-16 12:31:02

|

360人浏览过

|

来源于php中文网

原创

用sqrt判断需防浮点误差,推荐先转double取整再验证root²和(root+1)²;更稳妥用llround;或采用二分查找,以mid

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

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

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

实操建议:

  • long long 类型输入,先转成 double 调用 std::sqrt,再向下取整得 root
  • 计算 root * root(root + 1) * (root + 1),检查原数是否等于其中之一
  • 更稳妥的做法是用 std::llround(std::sqrt(x)) 后再验证,但需确保 x >= 0
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),无精度风险。

关键点:

立即学习C++免费学习笔记(深入)”;

  • 搜索范围是 [0, x],但可优化为 [0, min(x, 1LL (因为 sqrt(2^64) 最大是 2^32
  • 注意 mid * mid 可能溢出,应改用 mid 做条件判断(当 mid > 0
  • 边界情况:x == 0x == 1 必须覆盖
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 快速估算),比二分更快,也避免浮点误差——只要全程用整数除法。

PicWish
PicWish

推荐!专业的AI抠图修图,支持格式转化

下载

注意事项:

  • 迭代公式为 next = (cur + x / cur) / 2,必须用整数除法,且要防止 cur == 0
  • 初始值选 1 可大幅减少迭代次数
  • 必须在迭代前后检查 cur * cur == x,因为整数牛顿法可能上下震荡,不保证最后一次恰好命中
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 会丢失精度,必须靠整数方法兜底。

常见翻车点:

  • 忘记检查 x ,导致 sqrt 返回 NaN,后续比较失效
  • (int)sqrt(x) 截断而非四舍五入或向下取整,对 25, 36 等没问题,但对 999999999999999999 就错
  • 二分时写 mid = (left + right) / 2 导致 left + right 溢出(尤其 long long
  • 牛顿迭代未设终止条件,遇到某些值(如 x == 2)可能死循环

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

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

538

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

918

2023.09.19

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

402

2023.08.14

C++ 单元测试与代码质量保障
C++ 单元测试与代码质量保障

本专题系统讲解 C++ 在单元测试与代码质量保障方面的实战方法,包括测试驱动开发理念、Google Test/Google Mock 的使用、测试用例设计、边界条件验证、持续集成中的自动化测试流程,以及常见代码质量问题的发现与修复。通过工程化示例,帮助开发者建立 可测试、可维护、高质量的 C++ 项目体系。

3

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 6.7万人学习

C 教程
C 教程

共75课时 | 4万人学习

C++教程
C++教程

共115课时 | 12.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号