一个正整数 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 = s
tatic_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);
}
这个方法看似简洁,但实际使用中几个细节极易出错:
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 下对极大数的判断结果可能不同。