首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 實現阿姆斯壯數(水仙花數)查找:從暴力解法到高效能優化

     編輯:PHP 綜合知識

什麼是阿姆斯壯數?

阿姆斯壯數,又稱自冪數、水仙花數(專指 3 位數)。定義:一個 k 位數,其每位數字的 k 次方之和等於該數本身。

  • 3 位數(水仙花數):153 = 1³ + 5³ + 3³
  • 4 位數:1634 = 1⁴ + 6⁴ + 3⁴ + 4⁴
  • k 位數通式:Σ(digitᵢᵏ) = number

基礎實現(原始碼重構)

<?php
class Armstrong {
    /** 判斷單一數字是否為阿姆斯壯數 */
    public static function isArmstrong(int $num): bool {
        $digits = (string)$num;
        $k      = strlen($digits);
        $sum    = 0;
        foreach (str_split($digits) as $d) {
            // 使用 bcmath 避免大數溢位
            $sum = bcadd($sum, bcpow($d, $k));
        }
        return (string)$num === $sum;
    }

    /** 列印指定範圍內的所有阿姆斯壯數 */
    public static function listRange(int $start, int $end): void {
        for ($i = $start; $i <= $end; $i++) {
            if (self::isArmstrong($i)) {
                echo $i . PHP_EOL;
            }
        }
    }
}

// 使用範例
Armstrong::listRange(1, 100000);
/*
輸出:
1
2
3
4
5
6
7
8
9
153
370
371
407
1634
8208
9474
54748
92727
93084
*/
?>

效能優化策略

1. 預計算次方表(避免重複 bcpow)

<?php
class ArmstrongOptimized {
    private static array $powCache = [];

    private static function getPow(int $digit, int $exp): string {
        $key = $digit . '^' . $exp;
        return self::$powCache[$key] ??= bcpow((string)$digit, (string)$exp);
    }

    public static function isArmstrong(int $num): bool {
        $digits = (string)$num;
        $k      = strlen($digits);
        $sum    = '0';
        foreach (str_split($digits) as $d) {
            $sum = bcadd($sum, self::getPow((int)$d, $k));
        }
        return $sum === $digits;
    }
}
?>

2. 數學剪枝:利用上下界縮小搜尋空間

對於 k 位數,阿姆斯壯數必須滿足:

10k-1 ≤ Σ(digitᵢᵏ) ≤ k × 9ᵏ

當 k ≥ 60 時,k × 9ᵏ < 10k-1,不可能存在解。實際上最大阿姆斯壯數為 39 位數(已知有限 88 個)。

3. 併行搜尋(PHP 8.1+ Fibers / Swoole / ReactPHP)

<?php
// 使用 Swoole 進程池並行搜尋不同位數區間
use Swoole\Process\Pool;

$pool = new Pool(4); // 4 核心
$results = [];

for ($k = 1; $k <= 10; $k++) {
    $pool->dispatch(function () use ($k, &$results) {
        $start = 10 ** ($k - 1);
        $end   = min(10 ** $k - 1, 100_000_000);
        $found = [];
        for ($i = $start; $i <= $end; $i++) {
            if (ArmstrongOptimized::isArmstrong($i)) $found[] = $i;
        }
        return $found;
    });
}

while ($ret = $pool->read()) {
    $results = array_merge($results, $ret);
}
$pool->shutdown();
sort($results);
print_r($results);
?>

已知阿姆斯壯數完整列表(基數 10)

總共 88 個,最大者為 39 位數:

1-9 (1位)
153, 370, 371, 407 (3位)
1634, 8208, 9474 (4位)
54748, 92727, 93084 (5位)
548834 (6位)
1741725, 4210818, 9800817, 9926315 (7位)
24678050, 24678051, 88593477 (8位)
146511208, 472335975, 534494836, 912985153 (9位)
4679307774 (10位)
32164049650, 32164049651, 40028394225, 42678290603, 44708635679, 49388550606, 82693916578, 94204591914 (11位)
28116440335967 (14位)
4338281769391370, 4338281769391371 (16位)
21897142587612075, 35641594208964132, 35875699062250035 (17位)
1517841543307505039, 3289582984443187032, 4498128791164624869, 4929273885928088826 (19位)
63105425988599693916 (20位)
128468643043731391252, 449177399146038697307 (21位)
21887696841122916288858, 27879694893054074471405, 27907865009977052567814, 28361281321319229463398, 35452590104031691935943 (23位)
174088005938065293023722, 188451485447897896036875, 239313664430041569350093 (24位)
1550475334214501539088894, 1553242162893771850669378, 3706907995955475988644380, 3706907995955475988644381 (25位)
4422095118095899619457938 (26位)
121204998563613372405438066, 121270696006801314328439376, 128851796696487777842012787, 174650464499531377631639254, 177265453171792792366489765 (27位)
14607640612971980372614873089, 19008174136254279995012734740, 19008174136254279995012734741, 23866716435523975980390369295 (29位)
1145037275765491025924292050346, 1927890457142960697580636236639, 2309092682616190307509695338715 (31位)
17333509997782249308725103962772 (32位)
186709961001538790100634132976990, 186709961001538790100634132976991 (33位)
1122763285329372541592822900204593 (34位)
12639369517103790328947807201478392, 12679937780272278766342969289634603 (35位)
1219167219625434121569735803609966019, 12815792078366059955099770545296129367 (37位)
115132219018763992565095597973971522400, 115132219018763992565095597973971522401 (39位)

應用場景與變體

  • 面試經典題:考察迴圈、數學運算、大數處理(bcmath/gmp)。
  • 分散式計算演示:適合展示 MapReduce、Actor 模型分片計算。
  • 廣義阿姆斯壯數:不同進制(二進制、十六進制)、不同次方規則(如階乘和:因子翁數 145 = 1! + 4! + 5!)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved