迭代公式:X_{n+1} = (X_n + a/X_n) / 2,收斂條件 |X_{n+1} - X_n| < 1e-5。程式中初值 `x1 = a/2`,問為何選此初值?
求解 f(x) = x² - a = 0 的根。牛頓迭代公式:
x_{n+1} = x_n - f(x_n)/f'(x_n) = x_n - (x_n² - a)/(2x_n) = (x_n + a/x_n)/2
a/2 ≥ √a 當 a ≥ 4。對 `a ≥ 4`,`a/2` 滿足 `x₀ ≥ √a`,保證收斂。更嚴謹的初值選擇可用 `frexp` 取得指數部分估算,或查表法,但 `a/2` 在雙精度下通常 5-6 次迭代即達機器精度,足夠實用。
**實務直接用 `
#include
#include
int main() {
double a;
printf("輸入非負數: ");
scanf("%lf", &a);
if (a < 0) { printf("輸入錯誤\n"); return 1; }
printf("平方根 = %.10f\n", sqrt(a));
return 0;
}
原始回答提供的 `SquareRootFloat` 即為此算法變體。核心思想:
此算法在無硬體平方根指令的早期 GPU/CPU 上極快,現代 CPU 有 `RSQRTSS`/`SQRTSS` 指令,編譯器優化通常更優,但仍是位元操作經典教案。
#include
#include
float fast_inv_sqrt(float x) {
if (x == 0) return INFINITY;
float xhalf = 0.5f * x;
int i = *(int*)&x; // 位元重新解讀
i = 0x5f3759df - (i >> 1); // 魔術常數
x = *(float*)&i;
x = x * (1.5f - xhalf * x * x); // 牛頓法 1 次
x = x * (1.5f - xhalf * x * x); // 可選第 2 次
return x;
}
float fast_sqrt(float x) {
if (x <= 0) return 0;
return x * fast_inv_sqrt(x);
}
int main() {
float a;
printf("輸入非負數: ");
scanf("%f", &a);
printf("sqrt = %.8f\n", fast_sqrt(a));
printf("std = %.8f\n", sqrtf(a));
return 0;
}