上一篇
Java水仙花题需遍历100-999,拆分每位数字,若其立方和等于自身则输出,核心是循环+取余/整除操作分离
核心概念与原理
水仙花数(Narcissistic Number),又称阿姆斯特朗数(Armstrong Number),其定义为:一个 n 位数,其各位数字的 n 次方之和等于该数本身。
- 三位数:
153 = 1³ + 5³ + 3³ - 四位数:
8208 = 8⁴ + 2⁴ + 0⁴ + 8⁴
关键特性
| 属性 | 说明 |
|---|---|
| 位数依赖 | 需根据数字的实际位数计算对应次方(如三位数需计算立方) |
| 无前导零限制 | 仅针对自然数有效,忽略前导零(如 001 不视为合法输入) |
| 唯一性 | 同一位数范围内可能存在多个解(如三位数中有4个水仙花数) |
解题步骤详解
第一步:明确需求范围 默认求解 三位数 的水仙花数,但也可根据需求调整为任意位数,以下以三位数为例展开分析。
第二步:拆解数字并计算幂和
对每一个候选数执行以下操作:
- 分离各位数字:通过取模运算 和整除 逐步提取个位、十位、百位。
- 例:
num = 153→ 个位=153%10=3,剩余=153/10=15;十位=15%10=5,剩余=15/10=1;百位=1。
- 例:
- 计算各数字的立方和:将每位数字的立方相加。
- 例:
1³ + 5³ + 3³ = 1 + 125 + 27 = 153。
- 例:
- 比对结果:若立方和等于原数,则判定为水仙花数。
第三步:遍历所有可能的数
设置循环从最小值(如三位数的 100)到最大值(如 999),逐个验证是否符合条件。
Java实现方案
以下是完整的Java代码实现,包含详细注释:
public class NarcissisticNumber {
public static void main(String[] args) {
System.out.println("三位数的水仙花数如下:");
for (int num = 100; num <= 999; num++) {
int originalNum = num; // 保存原始数值用于后续比较
int sum = 0; // 存储各位立方和
int temp = num; // 临时变量用于逐位分解
// 分离各位数字并计算立方和
while (temp != 0) {
int digit = temp % 10; // 取最后一位数字
sum += Math.pow(digit, 3); // 计算立方并累加
temp /= 10; // 去掉最后一位
}
// 判断是否为水仙花数
if (sum == originalNum) {
System.out.println(originalNum);
}
}
}
}
代码关键点解析
| 代码片段 | 功能描述 | 注意事项 |
|---|---|---|
for (int num = 100; ... |
遍历所有三位数 | 修改起始/终止值可适配其他位数 |
Math.pow(digit, 3) |
计算单次方(此处固定为3次方) | 若需通用化,需动态获取位数 |
temp % 10 |
获取当前最低位数字 | 适用于任意进制下的低位提取 |
temp /= 10 |
移除已处理的最低位 | 确保循环终止条件正确性 |
典型输出结果
运行上述代码后,控制台将输出以下四个三位数的水仙花数:
| 序号 | 水仙花数 | 验证公式 |
|——|———-|——————————|
| 1 | 153 | 1³ + 5³ + 3³ = 153 |
| 2 | 370 | 3³ + 7³ + 0³ = 370 |
| 3 | 371 | 3³ + 7³ + 1³ = 371 |
| 4 | 407 | 4³ + 0³ + 7³ = 407 |
进阶扩展与优化
支持任意位数的水仙花数
若需查找非三位数的水仙花数(如四位、五位),需动态计算数字的位数 n,并将固定次方改为 n 次方,改进后的伪代码如下:
// 假设目标位数为 n int n = String.valueOf(num).length(); // 动态获取位数 sum += Math.pow(digit, n); // 使用动态次方
性能优化建议
- 预处理幂表:预先计算0~9的所有可能次方(如0³~9³),避免重复调用
Math.pow()。 - 并行计算:对大规模数据可采用多线程加速,尤其适用于高位数场景。
- 剪枝策略:利用数学规律提前排除不可能满足条件的数(如末位为偶数的某些组合)。
常见误区与调试技巧
易错点汇总
| 错误类型 | 表现现象 | 解决方案 |
|---|---|---|
| 死循环 | 未更新临时变量导致无限循环 | 确保每次迭代后更新 temp |
| 精度丢失 | 浮点数计算误差导致误判 | 改用整数运算或四舍五入 |
| 位数不匹配 | 错误地使用固定次方(如用平方代替立方) | 根据实际位数动态调整次方数 |
调试工具推荐
- IDE断点调试:逐步跟踪变量变化(如
sum的累积过程)。 - 单元测试:单独测试单个函数(如数字分解模块)。
- 日志打印:输出中间结果辅助定位问题。
FAQs
Q1: 为什么我的程序找不到任何水仙花数?
A: 可能原因包括:
- 循环范围错误:例如将三位数的上限设为
99而非999。 - 次方计算错误:误用了平方(
^2)而非立方(^3)。 - 类型转换问题:
Math.pow()返回double,可能导致精度丢失,建议强制转换为int后再比较。
Q2: 如何修改代码以查找四位数的水仙花数?
A: 只需调整两处:
- 循环范围:将
for (int num = 100; num <= 999; num++)改为for (int num = 1000; num <= 9999; num++)。 - 次方计算:将
Math.pow(digit, 3)改为Math.pow(digit, 4)。
修改后的代码可直接输出四位数的水仙花数(如8208, `94
