經典算法題:輸入實數 a,不使用 pow,輸出其立方根。本文提供基於二分法(區間折半)的完整 C 代碼,詳細解析邊界條件、正負數處理、精度控制,並對比牛頓迭代法優劣。
x³ - a = 0f(x) = x³ - a 單調遞增(導數 3x² ≥ 0)。f(x) = 0 的根,即 x = a^(1/3)。n=0, m=a(a>0);n=a, m=0(a<0)。x=(n+m)/2,根據 f(x) 正負縮小區間。#include <stdio.h>
int main() {
double a, n, m, x;
scanf("%lf", &a);
// 1. 初始化搜索區間
if (a >= 0) {
n = 0;
m = a;
} else {
n = a; // 負數立方根為負,區間 [a, 0]
m = 0;
}
// 2. 二分迭代
while (1) {
x = (n + m) / 2.0;
double fx = x * x * x - a; // f(x) = x³ - a
if (a >= 0) {
if (fx <= 0) n = x; // 根在右半區間
else m = x; // 根在左半區間
} else {
if (fx <= 0) m = x; // 負數區間邏輯反轉
else n = x;
}
// 3. 精度判斷:|x³ - a| < 1e-6
if (fx <= 1e-6 && fx >= -1e-6) break;
}
printf("%lf %lf\n", x, x * x * x); // 輸出立方根及驗證值
return 0;
}
| 細節 | 處理方式 | 原因 |
|---|---|---|
| 負數輸入 | 區間設為 [a, 0],判斷邏輯反轉 | 負數立方根為負,單調性不變但區間翻轉 |
| a=0 | 直接輸出 0 | 避免除零/無限循環 |
| 精度控制 | |x³ - a| < 1e-6 | 題目通常要求 6 位小數精度 |
| 溢出風險 | 用 double,x*x*x 範圍足夠 | 避免 int 溢出 |
| 無限循環保護 | 可加最大迭代次數 (如 100 次) | 極端情況下防掛死 |
double cbrt_newton(double a) {
if (a == 0) return 0;
double x = a; // 初始猜測
for (int i = 0; i < 20; i++) {
double prev = x;
x = (2.0 * x + a / (x * x)) / 3.0; // x_{n+1} = (2x_n + a/x_n²)/3
if (fabs(x - prev) < 1e-12) break;
}
return x;
}
x=0 除零、初始值選擇敏感。輸入: 8 輸出: 2.000000 8.000000
輸入: 27 輸出: 3.000000 27.000000
輸入: -8 輸出: -2.000000 -8.000000
輸入: 0.001 輸出: 0.100000 0.001000
輸入: 1000000 輸出: 100.000000 1000000.000000
scanf("%lf", &a) 讀 double 必須用 %lf。printf("%lf", x) 印 double 用 %lf (C99) 或 %f。fabs(fx) < EPS 而非 fx == 0。while (m - n > EPS) 替代 while(1) 更規範。二分法是數值計算的瑞士軍刀:單調函數求根、查找插入位置、浮點數二分答案,萬變不離其宗。掌握「區間初始化、中點測試、邊界收縮、精度終止」四步法,這類題目穩拿滿分。