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

C++中asin/acos函数输出-nan Ind异常问题求助

C++中acos/asin导致NaN输出的问题排查与解决

问题场景

需要实现的公式:

F = cos²(p(x)) + sin²(p(y)) + p(z)
p(k) = arccos(a * k) + arcsin(k)

编写的C++代码在输入x=1.20、y=3.05、z=2.00时输出-nan Ind,但将acos/asin替换为cos/sin后运行正常。原代码如下:

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

using namespace std;

const double a = 0.01;

double p(double k) {
    double p1;
    p1 = acos(a * k) + asin(k);
    return (p1);
}

int main() {
    double x;
    double y;
    double z;
    double F;

    cout << "x = "; cin >> x;
    cout << "y = "; cin >> y;
    cout << "z = "; cin >> z;

    F = pow(cos(p(x)), 2) + pow(sin(p(y)), 2) + p(z);

    cout << "F = " << F << endl;

    return 0;
}

问题原因

C++标准库中acos()和asin()的参数必须严格落在[-1, 1]区间内,如果参数超出这个范围,函数会返回NaN(非数值),后续所有依赖这个值的计算都会变成NaN,最终输出-nan Ind。

对应输入的数值:

  • y=3.05:计算asin(3.05)时,3.05远大于1,超出asin的定义域,直接返回NaN
  • z=2.00:asin(2.00)同样超出[-1,1]范围,返回NaN
  • 而cos()和sin()的参数可以是任意实数,所以替换后不会出现定义域问题,运行正常。

解决方法

1. 参数范围钳制

在计算acos和asin前,先将参数限制在[-1, 1]区间内。可以手动实现钳制逻辑,或者使用C++17及以上标准的std::clamp函数(需包含<algorithm>头文件)。

2. 输入合法性校验

在接收用户输入时,判断输入的k是否满足|k| ≤ 1(因为a=0.01,|a*k| ≤ 0.01 ≤1,所以只需限制k在[-1,1]即可),若超出范围则提示用户重新输入。

修改后的代码示例

以下是添加参数钳制的版本:

#include <iostream>
#include <math.h>
#include <algorithm> // 用于std::clamp

using namespace std;

const double a = 0.01;

// 手动实现钳制(兼容C++17之前的版本)
double clamp(double val, double min_val, double max_val) {
    if (val < min_val) return min_val;
    if (val > max_val) return max_val;
    return val;
}

double p(double k) {
    double acos_arg = clamp(a * k, -1.0, 1.0);
    double asin_arg = clamp(k, -1.0, 1.0);
    return acos(acos_arg) + asin(asin_arg);
}

int main() {
    double x;
    double y;
    double z;
    double F;

    cout << "x = "; cin >> x;
    cout << "y = "; cin >> y;
    cout << "z = "; cin >> z;

    F = pow(cos(p(x)), 2) + pow(sin(p(y)), 2) + p(z);

    cout << "F = " << F << endl;

    return 0;
}

如果使用C++17及以上,可直接替换手动的clamp函数为std::clamp:

double p(double k) {
    double acos_arg = std::clamp(a * k, -1.0, 1.0);
    double asin_arg = std::clamp(k, -1.0, 1.0);
    return acos(acos_arg) + asin(asin_arg);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:20:37