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

使用Newton法求解石墨烯盈亏平衡量时输出异常,求逻辑错误排查

牛顿法计算盈亏平衡石墨烯量的程序错误排查

我尝试用牛顿法近似计算公司每日实现盈亏平衡所需的最小石墨烯量,但程序运行输出异常值(inf、nan),以下是我的C++代码及运行输出,恳请帮忙排查问题:

原代码

#include <iostream>
#include <iomanip>
#include <math.h>
#include <cmath>

using namespace std;
void getStartingGuess(double&);
void calcRoots(double&);
double calcProfits(double);
double calcDerivative(double);

int main()
{
    double initialVal;
    getStartingGuess(initialVal);
    calcRoots(initialVal);
}

void getStartingGuess(double& initialVal)
{
    cout << "Enter a positive initial value: ";
    cin >> initialVal;
    if (initialVal < 0)
    {
        cout << "Invalid value, please re-enter:";
        cin >> initialVal;
    }
}

void calcRoots(double& initialVal)
{
    double profit, profitderiv, estimate;
    {
        for (int i = 1; i <= 5; ++i)
        {
            profit = calcProfits(initialVal);
            profitderiv = calcDerivative(initialVal);
            estimate = initialVal - (profit) / (profitderiv);
            cout << fixed << setprecision(3);
            cout << "#Iteration #" << i << ":" << estimate << endl;
            initialVal = estimate;
        }
        cout << "The final approximation is : " << estimate;
    }
}

double calcProfits(double initialVal)
{
    double profit;
    profit = -1000 + 2 * initialVal - (3 * pow(initialVal, 2 / 3));
    return profit;
}

double calcDerivative(double initialVal)
{
    double profitderiv;
    profitderiv = 2 - (2 / pow(initialVal, 1 / 3));
    return profitderiv;
}

运行输出

Enter a positive initial value: 2
#Iteration #1:inf
#Iteration #2:nan
#Iteration #3:nan
#Iteration #4:nan
#Iteration #5:nan
The final approximation is : nan
Process returned 0 (0x0)   execution time : 4.398 s
Press any key to continue.

问题排查与修复

核心错误:整数除法导致指数计算错误

C++中整数之间的除法会直接舍弃小数部分,比如2/3结果是0,1/3结果也是0。这会导致:

  • calcProfits中pow(initialVal, 2/3)变成pow(initialVal, 0),结果恒为1,利润函数完全偏离预期
  • calcDerivative中pow(initialVal, 1/3)变成pow(initialVal, 0),结果为1,进而计算出2 / 1 = 2,导数变为2 - 2 = 0,第一次迭代时除以0直接得到inf,后续迭代因无效值产生nan

修复步骤

  1. 修正整数除法为浮点数除法
    将calcProfits中的2 / 3改为2.0 / 3,calcDerivative中的1 / 3改为1.0 / 3,确保指数是正确的浮点数。

  2. 完善初始值输入验证
    原代码只检查一次输入,若用户再次输入负数仍会接受,改为循环验证直到输入正数:

    void getStartingGuess(double& initialVal)
    {
        do {
            cout << "Enter a positive initial value: ";
            cin >> initialVal;
            if (initialVal <= 0) {
                cout << "Invalid value, please re-enter." << endl;
            }
        } while (initialVal <= 0);
    }
    
  3. 增加导数为0的判断(可选)
    为避免再次出现除以0的情况,在calcRoots中加入判断,若导数接近0则终止迭代或提示:

    void calcRoots(double& initialVal)
    {
        double profit, profitderiv, estimate;
        const double eps = 1e-9;
        for (int i = 1; i <= 5; ++i)
        {
            profit = calcProfits(initialVal);
            profitderiv = calcDerivative(initialVal);
            if (fabs(profitderiv) < eps) {
                cout << "Derivative is zero, cannot proceed with iteration." << endl;
                break;
            }
            estimate = initialVal - (profit) / (profitderiv);
            cout << fixed << setprecision(3);
            cout << "#Iteration #" << i << ":" << estimate << endl;
            initialVal = estimate;
        }
        cout << "The final approximation is : " << estimate;
    }
    

修复后的完整代码

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;
void getStartingGuess(double&);
void calcRoots(double&);
double calcProfits(double);
double calcDerivative(double);

int main()
{
    double initialVal;
    getStartingGuess(initialVal);
    calcRoots(initialVal);
}

void getStartingGuess(double& initialVal)
{
    do {
        cout << "Enter a positive initial value: ";
        cin >> initialVal;
        if (initialVal <= 0) {
            cout << "Invalid value, please re-enter." << endl;
        }
    } while (initialVal <= 0);
}

void calcRoots(double& initialVal)
{
    double profit, profitderiv, estimate;
    const double eps = 1e-9;
    for (int i = 1; i <= 5; ++i)
    {
        profit = calcProfits(initialVal);
        profitderiv = calcDerivative(initialVal);
        if (fabs(profitderiv) < eps) {
            cout << "Derivative is zero, cannot proceed with iteration." << endl;
            break;
        }
        estimate = initialVal - (profit) / (profitderiv);
        cout << fixed << setprecision(3);
        cout << "#Iteration #" << i << ":" << estimate << endl;
        initialVal = estimate;
    }
    cout << "The final approximation is : " << estimate;
}

double calcProfits(double initialVal)
{
    double profit;
    profit = -1000 + 2 * initialVal - (3 * pow(initialVal, 2.0 / 3));
    return profit;
}

double calcDerivative(double initialVal)
{
    double profitderiv;
    profitderiv = 2 - (2 / pow(initialVal, 1.0 / 3));
    return profitderiv;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 15:41:12