← PHP中阶乘计算的两种实现方式:循环与递归 PHP中回文数的判定:数字反转与比较 →

PHP中阿姆斯特朗数的判定:拆解数字与立方求和

原创 2026-05-21 PHP 已有人查阅

什么是阿姆斯特朗数

阿姆斯特朗数(Armstrong Number),也叫做自幂数(Narcissistic Number),指的是一个 n 位数,其各个位上的数字的 n 次幂之和等于它本身。

对于三位数来说,就是每位数字的立方和等于该数本身。

常见的阿姆斯特朗数有:0、1、153、370、371、407、1634等。

具体验证(以407为例):

407 = 4³ + 0³ + 7³
    = 64 + 0 + 343
    = 407

个人经验:很多资料只说“立方和”,但严格来说那是针对三位数的特殊情况。像1634是四位数,需要计算的是4次方和。初学阶段通常先掌握三位数的立方和版本,理解之后再扩展到通用次方。

核心实现逻辑

判定一个数是否为阿姆斯特朗数,需要以下几个步骤:

  1. 保存原始数值(后面需要做比较)

  2. 用循环逐位取出每一位数字(通过取模和整除)

  3. 对每一位数字进行立方运算并累加

  4. 循环结束后,比较累加和与原始数值

关键操作符

  • % 取模运算符:得到之后一位数字

  • / 除法运算:去掉之后一位数字

示例一:判定固定数字407

下面这段代码展示了如何判定407是不是阿姆斯特朗数。

<?php  
$num = 407;  
$sum = 0;  
$temp = $num;      // 保存原始值,因为后面$temp会被修改

while ($temp != 0) {  
    $remainder = $temp % 10;           // 取出之后一位
    $sum = $sum + $remainder * $remainder * $remainder;  // 立方后累加
    $temp = (int)($temp / 10);         // 去掉之后一位,注意强制转整数
}  

if ($num == $sum) {  
    echo "{$num} 是阿姆斯特朗数";  
} else {  
    echo "{$num} 不是阿姆斯特朗数";  
}  
?>

输出407 是阿姆斯特朗数

注意上面代码中的一个细节$temp = (int)($temp / 10) 这里用 (int) 强制转换。PHP中除法运算的结果可能是浮点数,比如 407/10 = 40.7,转换成整数后变为40,这样才能继续循环。如果忘记转换,浮点数取模运算会出现意料之外的结果。

示例二:通过表单动态判定任意数字

代码号学习编程中,用表单接收用户输入是常见的交互方式。

<html>  
<body>  
    <form method="post">  
        请输入一个数字:  
        <input type="number" name="number" step="1">  
        <input type="submit" value="判断阿姆斯特朗数">  
    </form>  
</body>  
</html>  
<?php  
if ($_POST) {   
    $number = $_POST['number'];  
    
    // 输入有效性检查
    if (!is_numeric($number) || $number < 0) {  
        echo "请输入有效的非负整数";  
    } else {  
        $temp = $number;  
        $sum = 0;  
        
        while ($temp != 0) {  
            $remainder = $temp % 10;  
            $sum = $sum + ($remainder * $remainder * $remainder);  
            $temp = (int)($temp / 10);  
        }  
        
        if ($number == $sum) {  
            echo "{$number} 是阿姆斯特朗数";  
        } else {  
            echo "{$number} 不是阿姆斯特朗数";  
        }  
    }  
}  
?>     

示例三:找出指定范围内的所有阿姆斯特朗数

这个扩展例子展示了如何批量查找,对于学习循环嵌套有参考价值。

<?php  
$start = 1;  
$end = 1000;  

echo "{$start} 到 {$end} 之间的阿姆斯特朗数有:<br>";

for ($num = $start; $num <= $end; $num++) {  
    $sum = 0;  
    $temp = $num;  
    
    while ($temp != 0) {  
        $remainder = $temp % 10;  
        $sum = $sum + ($remainder * $remainder * $remainder);  
        $temp = (int)($temp / 10);  
    }  
    
    if ($num == $sum) {  
        echo $num . " ";  
    }  
}  
?>

输出1 153 370 371 407

本节课程知识要点

知识点 说明
数字拆分技巧 反复用%10取末位,用/10去掉末位
类型转换 PHP除法可能产生浮点数,需要(int)转换后再继续循环
原始值保存 循环过程中会修改临时变量,必须先保存原始值用于最终比较
边界条件 0和1也满足定义(0^3=0, 1^3=1),需要正确处理

扩展到n位数的自幂数判定

三位数的立方和判定是特例。如果要写一个更通用的函数,应该计算数字的位数,然后计算每位数字的位数次方之和。

function isArmstrong($num) {
    $original = $num;
    $digits = str_split((string)$num);
    $power = count($digits);
    $sum = 0;
    
    foreach ($digits as $digit) {
        $sum += pow((int)$digit, $power);
    }
    
    return $sum == $original;
}

echo isArmstrong(1634) ? "是" : "不是";  // 1634: 1⁴+6⁴+3⁴+4⁴ = 1634

为什么要用字符串方式处理:用数学方式(反复取模)需要预先知道数字位数,或者先统计位数再处理。用str_split转换成数组更直观,但要注意这种写法引入了字符串转换的开销。对于学习阶段来说两种方式都可以理解。

常见问题与排查

问题1:判断153时返回false

  • 可能原因:$temp/10没有转整数,导致浮点数累积误差

  • 解决:用intdiv($temp, 10) 或 (int)($temp/10)

问题2:输入0时循环不执行

  • 分析:while($temp != 0) 在temp=0时直接跳过,temp=0时直接跳过,sum保持0,与原始值相等,结果正确。但逻辑上应该单独处理,方便他人阅读理解

问题3:大数判定结果错误

  • 原因:PHP整数溢出或立方和超过变量范围

  • 解决:对于大数判定,用BCMath扩展的任意精度函数

个人经验分享

当初学这个知识点时,我犯过一个低级错误——直接拿着$num做循环,之后拿修改过的$num去比较累加和,结果对不上。后来才意识到需要复制一份临时变量。这个小细节现在看起来很简单,但当时确实卡了一会儿。

另外说一下为什么不用pow($remainder,3)而写成$remainder*$remainder*$remainder。两个写能一样,但乘法运算比函数调用更快。虽然对于单个判定来说差别可以忽略,但如果在循环中频繁调用,或者在做范围查找时要执行成千上万次,乘法方式的性能会好一些。不是说要刻意优化,而是养成写高效代码的习惯。

← PHP中阶乘计算的两种实现方式:循环与递归 PHP中回文数的判定:数字反转与比较 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号