最近有開發者遇到一個經典的 C 語言問題:控制台程序能正常接收兩次輸入,但卻完全沒有任何輸出,程序看起來像是「卡死」了一樣。經過代碼審查,問題出在平方根計算函數 squreRoot 的邏輯錯誤上。
原代碼中 squreRoot 函數存在嚴重的邏輯缺陷:
float squreRoot (float x, float esplion)
{
float guess = 1.0;
while (absolutevalue (guess*guess - x) >= esplion ) {
int i;
for (i = 0; i <= times(esplion); i++) {
guess = (x/guess + guess)/2.0;
printf ("The guess is %f.\n", guess);
}
}
return guess;
}
while 循環條件依賴 guess 收斂,但內層 for 循環每次執行 times(esplion) 次迭代。若 times 返回值較大,程序會在內層循環長時間執行,外層條件無法及時檢查,導致看似「無輸出」。times 函數邏輯缺陷:while (esplion != 1) 當 esplion 為小數(如 0.001)時,乘 10 後永遠無法精確等於 1(浮點數精度問題),導致 times 陷入死循環,程序根本跑不到 squreRoot。times(esplion) 在每次外層循環都被調用,重複計算。// 修正 times 函數:改用對數計算避免死循環
int times(float epsilon) {
if (epsilon <= 0) return 0;
return (int)ceil(-log10(epsilon)); // 計算需要乘幾次 10 達到 1
}
// 優化 squreRoot:移除內層 for 循環,直接牛頓迭代
float squareRoot(float x, float epsilon) {
if (x < 0) return -1; // 錯誤處理
float guess = x / 2.0; // 更好的初始猜測
if (guess == 0) guess = 1.0;
while (absoluteValue(guess * guess - x) >= epsilon) {
guess = (x / guess + guess) / 2.0;
// 可選:打印調試信息
// printf("Guess: %f\n", guess);
}
return guess;
}
times 改為對數計算,消除浮點數比較導致的死循環for 循環,牛頓法單次迭代即可收斂修正後程序能正常輸出計算過程與最終結果,解決「有輸入無輸出」的假象。