本文提供一個高效的質因數分解程序,支持unsigned long long全範圍(2^64-1),包含邊界檢查、編譯鏈接技巧與性能分析。
#include
#include
#include
#include
int main(int argc, char **argv) {
unsigned long long data = 0, i = 0, max = 0;
// 參數檢查
if (argc < 2) {
printf("Usage: %s \n", argv[0]);
return -1;
}
if (strlen(argv[1]) > 19) { // ULLONG_MAX約20位
printf("out of range\n");
return -1;
}
data = atoll(argv[1]);
// 特殊邊界:2^63-1 = 9223372036854775807
if (9223372036854775807ULL == data && (argv[1][18]=='8' || argv[1][18]=='9')) {
printf("out of range\n");
return -1;
}
printf("data : %llu\n", data);
// 試除法分解
while (1) {
max = sqrt(data); // 動態更新上界
for (i = 2; i <= max; i++) {
if (data % i == 0) {
data /= i;
printf("%llu * ", i);
fflush(stdout); // 即時輸出
break;
}
}
if (i > max) { // 剩餘data為質數
printf("%llu\n", data);
break;
}
}
return 0;
}
gcc -o factor factor.c -lm
原因:sqrt()定義在libm中,非標準C庫,需顯式鏈接-lm。
2^64-1)%llu (printf/scanf)atoll() / strtoull()data變小,sqrt(data)顯著降低循環次數fflush(stdout)保證大數分解時逐步顯示結果break,避免繼續無效試除ULLONG_MAX邊界值特殊判斷(atoll行為未定義)atoll忽略,建議用strtoull嚴格解析| 輸入規模 | 試除法耗時 | 建議算法 |
|---|---|---|
| < 10^12 | 毫秒級 | 試除法足夠 |
| 10^12 ~ 10^16 | 秒~分鐘級 | Pollard's Rho |
| > 10^16 | 極慢 | 二次篩法/數域篩 |
// 核心思想:隨機多項式序列 + Floyd循環檢測 + GCD提取因子
unsigned long long pollard_rho(unsigned long long n) {
if (n%2==0) return 2;
if (is_prime(n)) return n;
while(1) {
unsigned long long c = rand()%(n-1)+1;
unsigned long long x = rand()%n, y = x, d = 1;
while(d==1) {
x = (mul_mod(x,x,n)+c)%n;
y = (mul_mod(y,y,n)+c)%n;
y = (mul_mod(y,y,n)+c)%n;
d = gcd(abs(x-y), n);
}
if(d!=n) return d;
}
}
// 需配合 Miller-Rabin 質數測試、模乘防溢出
strtoull檢查errno與endptr10^14建議接入GMP庫(mpz_factor)2^3 * 3 * 5^2形式試除法實現簡單、無依賴、適合中小規模數值分解。關鍵點在於-lm鏈接、unsigned long long類型使用、動態sqrt上界優化。面對大數分解需求,應升級為概率性算法並引入專業大數庫。