水仙花数指n位正整数,其各位数字的n次方和等于自身;C++中需先求位数n,再用循环取位与整数幂计算,避免pow精度问题。

什么是水仙花数,C++里怎么定义边界
水仙花数(Narcissistic number)特指一个 n 位正整数,其各位数字的 n 次方之和等于它本身。注意:严格来说,水仙花数只针对三位数(即 n == 3),而四位及以上叫“自幂数”或“阿姆斯特朗数”。但很多题目混用,所以得先确认需求——如果题干说“判断水仙花数”,默认按三位处理;若要求通用,就得动态算位数和幂次。
常见误区是直接写死 pow(10, 3) 或硬编码三位判断,结果对 9474(四位、9^4 + 4^4 + 7^4 + 4^4 == 9474)就漏判。所以关键第一步是求出数字的位数 n,再逐位取幂求和。
如何安全提取每位数字并计算 n 次方
C++ 中用 % 10 和 / 10 循环取位最稳妥,避免字符串转换带来的额外开销和符号问题。但要注意:pow() 返回 double,对大整数易失精度(比如 pow(9, 10) 可能返回 3486784400.999999),强制转 int 会截断出错。必须自己写整数幂函数,或用 std::pow 后四舍五入再转整型(不推荐)。
- 用循环累乘实现整数幂,例如
int ipow(int base, int exp),确保无精度损失 - 原数需保存副本,因为取位过程会修改它(或用
abs()处理负数输入) - 位数统计建议用
while (tmp) { n++; tmp /= 10; },比转字符串快且无依赖
完整可运行的判断函数(支持任意位数)
bool isArmstrong(int num) {
if (num < 0) return false;
int original = num;
int n = 0, tmp = num;
while (tmp) { n++; tmp /= 10; }
int sum = 0;
tmp = original;
while (tmp) {
int digit = tmp % 10;
int power = 1;
for (int i = 0; i < n; ++i) power *= digit; // 整数幂,无 double 陷阱
sum += power;
tmp /= 10;
}
return sum == original;
}
这个版本没用 <cmath>,规避了 pow 的浮点误差;支持从 0 到 INT_MAX 范围内所有非负整数(超过 int 范围的数需改用 long long 并注意幂运算溢出)。测试时发现 0 算作 1 位数,0^1 == 0,所以 isArmstrong(0) 返回 true —— 这符合数学定义,但有些题目明确排除 0,需按需加 if (num == 0) return false;。
立即学习“C++免费学习笔记(深入)”;
性能与边界情况提醒
对大数(如 10 位以上),幂运算和累加可能溢出 int。例如 9^10 == 3486784401 已超 INT_MAX(约 21 亿),此时 sum 会回绕为负数,导致误判。实际使用中,若输入范围不可控,应在幂计算前加溢出检查,或直接用 long long 存储 sum 和中间幂值。
另外,isArmstrong(153) 返回 true,isArmstrong(371) 也 true,但 isArmstrong(1634)(四位)同样 true —— 它不是传统“水仙花数”,却是自幂数。别被名字带偏,看题干到底要三位限定,还是泛指自幂数。


















