一个正整数 n 是斐波那契数当且仅当 5×n²+4 或 5×n²−4 至少有一个为完全平方数;需用 sqrtl 和双根验证防浮点误差,注意溢出与平台精度差异。

用数学公式法快速判断是否为斐波那契数
一个正整数 n 是斐波那契数,当且仅当 5 * n * n + 4 或 5 * n * n - 4 中至少有一个是完全平方数。这是基于比内公式(Binet’s formula)和整数性质推导出的充要条件,比生成序列或二分查找更高效,时间复杂度为 O(1)(忽略开方运算的底层成本)。
如何判断一个数是不是完全平方数
C++ 标准库没有直接判断完全平方数的函数,需手动验证。关键是避免浮点误差导致误判,尤其对大整数(如 long long 范围内的值)。
- 先用
sqrt计算近似平方根,类型转为long long向下取整 - 再检查
root * root == x和(root + 1) * (root + 1) == x,覆盖四舍五入偏差 - 不推荐只用
round(sqrt(x)),因为sqrt对大整数可能丢失精度
完整可运行的判断函数(含边界处理)
以下函数支持 unsigned long long 输入,能正确处理最大到约 1e19 的数(取决于 sqrtl 实现精度)。注意:输入必须为正整数,0 和 1 都是合法斐波那契数(F₀=0, F₁=1)。
bool isPerfectSquare(unsigned long long x) {
if (x < 2) return true;
unsigned long long root = static_cast(sqrtl(x));
return (root * root == x) || ((root + 1) * (root + 1) == x);
}
bool isFibonacci(unsigned long long n) {
if (n == 0) return true;
unsigned long long x1 = 5 n n + 4;
unsigned long long x2 = 5 n n - 4;
return isPerfectSquare(x1) || isPerfectSquare(x2);
}
容易踩的坑和兼容性提醒
这个方法看似简洁,但实际使用中几个细节极易出错:
立即学习“C++免费学习笔记(深入)”;
-
5 * n * n可能溢出 —— 必须确保n类型足够宽,比如用unsigned long long;若传入int且n > 46340,乘法就已溢出 -
sqrtl比sqrt更适合long double,但在某些平台(如 Windows + MinGW)精度仍不足;可改用整数牛顿法规避浮点依赖 - 负数未定义 —— 函数不处理负输入,调用前应明确约定输入范围
- 该公式对
0成立(5*0+4 = 4是平方数),但部分实现漏判0,需单独处理
真正棘手的不是逻辑,而是数值边界和浮点实现差异——同一段代码在 Linux GCC 和 macOS Clang 下对极大数的判断结果可能不同。










