一个正整数 n 是斐波那契数当且仅当 5×n²+4 或 5×n²−4 至少一个是完全平方数;判断时需用四舍五入取整再验证平方,避免浮点精度误差。

用数学性质快速判断,别暴力生成数列
直接生成斐波那契数列再逐个比对,时间复杂度高、还可能溢出。更可靠的做法是利用一个经典数学性质:**一个正整数 n 是斐波那契数,当且仅当 5 * n * n + 4 或 5 * n * n - 4 中至少一个是完全平方数**。
这个判定基于比内公式(Binet's formula)的逆向推导,对任意 int 或 long long 都能常数时间完成,无需循环或递归。
检查完全平方数时要注意浮点精度陷阱
C++ 中用 sqrt 得到的是 double,直接取整再平方容易因精度丢失误判,比如 sqrt(25) 可能返回 4.999999999 导致 floor 后变成 4。
安全做法是:先用 sqrt 算近似值,四舍五入取整为 long long,再验证该整数的平方是否严格等于原数:
bool isPerfectSquare(long long x) {
if (x
-
round比floor或trunc更稳妥,能覆盖浮点误差方向不确定的情况 - 必须用
long long存储r和做乘法,避免int溢出(例如n = 1e9时5*n*n远超int范围) - 输入为负数时直接返回
false,斐波那契数列在标准定义中只含非负整数(0, 1, 1, 2, 3, 5...)
完整判定函数要处理边界和类型兼容性
标准斐波那契数列包含 0 和 1,这两个数必须被正确识别。同时,用户传入的可能是 int、unsigned int 或 long,函数签名建议统一用 long long 输入,兼顾范围与兼容性:
bool isFibonacci(long long n) {
if (n
- 不要忽略
n == 0:此时s2 = -4,isPerfectSquare会返回false,但s1 = 4是完全平方数,整体返回true,正确 - 如果项目要求支持
unsigned类型输入,注意5*n*n - 4在n == 0或n == 1时可能回绕成极大正数,所以仍建议先转为有符号大整型再计算 - 该方法不适用于浮点输入——不是所有小数都能精确表示,也不在斐波那契数定义域内
性能和可移植性细节不能漏
这个判定在绝大多数平台上都是常数时间,但有两个实际约束:
-
sqrt对于极大值(如接近LLONG_MAX)可能返回inf,此时round(inf)是未定义行为;实际中只要n不超过约1e9,5*n*n+4就不会溢出long long(假设long long是 64 位) - 某些嵌入式平台或严格模式下
<cmath></cmath>的sqrt可能不支持long long,需显式转为double或long double;若精度不够,可改用整数开方(如二分查找),但日常应用极少需要 - 若需线程安全,确保
sqrt调用不依赖全局状态——标准库实现通常满足这点
真正容易被忽略的是:这个判定只对**数学定义下的斐波那契数列**有效,即从 F₀=0, F₁=1 开始的标准序列。如果业务中用的是从 1, 1 开始、不含 0 的变体,得额外排除 n == 0 的情况。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











