You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言牛顿迭代求根函数参数异常及死循环问题求助

问题分析与修复方案

你遇到的问题主要来自多个语法错误、逻辑错误以及变量使用不当,下面逐个拆解并给出解决思路:

1. 函数返回值类型错误

你的sqrtNR函数声明为void,但最后却尝试返回x(return x;),这属于未定义行为,会导致编译器处理混乱,直接影响返回值的正确性。

修复: 将函数返回类型改为double,确保正确返回计算结果:

double sqrtNR(double num) {
    // ... 函数内容 ...
    return x;
}

2. 格式化输出的格式符错误

你用%d(整数格式符)来打印double类型的num和x,这会导致内存解析错误,出现莫名其妙的输出(比如OnlineGDB返回8、DEV-C++返回0)。

修复: 打印浮点数应该用%lf或%f:

printf("\nnum: %lf\n", num);
printf("x: %lf\n", x);
// 其他打印x的地方同理

3. 牛顿迭代公式错误(核心问题)

你要计算的是平方根,但却用了立方根的牛顿迭代公式!

  • 平方根的迭代公式:$x_{n+1} = \frac{1}{2}(x_n + \frac{num}{x_n})$(对应导数$f'(x)=2x$)
  • 你定义的g(x,num)是$\frac{1}{3}(2x + \frac{num}{x})$,这是立方根的迭代公式,会导致迭代无法收敛到正确的平方根,甚至进入死循环。

修复: 修正迭代公式,直接在代码中使用正确的计算式:

// 循环内的迭代语句替换为:
x = 0.5 * (x + num / x);
// 等价于 x = x - (x*x - num)/(2*x);

4. 全局变量导致的数值污染

你把x、i、num都声明为全局变量,这会导致:

  • i没有初始化,第一次循环时是随机值,后续调用函数也不会重置
  • 全局num和函数参数num同名,容易造成逻辑混淆
  • 全局x会保留上次调用的结果,影响下一次计算

修复: 将这些变量改为函数内的局部变量,避免全局污染:

double sqrtNR(double num) {
    double x = num; // 局部变量x,初始值设为num
    int i = 0; // 局部变量i,初始化0
    // ... 循环内容 ...
}

5. 循环条件与输入校验的完善

虽然var < fabs(f(x,num))逻辑上等价于fabs(f(x,num)) > var,但后者可读性更强;另外需要增加负数输入的校验,避免无意义的迭代。

修复: 完善循环条件和输入校验:

// 在函数开头判断输入是否非负
if (num < 0) {
    printf("Error: 负数没有实数平方根\n");
    return NAN; // 需要包含math.h
}
// 循环条件更清晰
for (; fabs(x*x - num) > var; i++) {
    x = 0.5 * (x + num / x);
}

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define var 1E-10 // 精度阈值

double sqrtNR(double num) {
    // 校验输入合法性
    if (num < 0) {
        printf("Error: 负数无实数平方根\n");
        return NAN;
    }
    double x = num; // 迭代初始值
    int i = 0; // 迭代次数计数器,初始化0
    
    printf("\n初始num: %lf\n", num);
    printf("初始x: %lf\n", x);
    
    // 牛顿迭代循环
    for (; fabs(x*x - num) > var; i++) {
        x = 0.5 * (x + num / x);
        printf("第%d次迭代后x: %lf\n", i+1, x); // 可选:打印迭代过程
    }
    
    printf("迭代次数: %d\n", i);
    return x;
}

int main(int argc, char** argv) {
    double num;
    printf("请输入一个非负数:\n");
    scanf("%lf", &num);
    printf("你输入的数是:%lf\n", num);
    
    double result = sqrtNR(num);
    printf("计算得到的平方根:%lf\n", result);
    // 可以和标准库sqrt对比验证
    printf("标准库sqrt结果:%lf\n", sqrt(num));
    
    return 0;
}

验证说明

修复后,无论在OnlineGDB还是DEV-C++中运行,都能正确计算平方根:

  • 输入4会返回2.0,输入2会返回约1.41421356
  • 不会再出现死循环,因为迭代公式正确,能快速收敛到精度阈值内

内容的提问来源于stack exchange,提问作者HelloMyNameIsDennis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:03:31