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的定义域,直接返回NaNz=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
相关产品推荐
相关产品推荐

