C语言单函数返回向量点积与夹角时报-nan(ind)如何解决
问题解答
功能实现可行性确认
可以通过指针实现单个函数同时返回两个计算结果,C语言本身不支持函数直接返回多个值,通过指针参数修改外部变量的存储值是多返回值场景最常用的实现方案。
现有代码问题排查
触发-nan(ind)错误以及无法同时返回两个结果的原因如下:
- 返回值逻辑错误:C语言中
return(dot,theta)属于逗号表达式,只会返回最后一个值theta,double类型的返回值永远无法同时带出点积结果 - 夹角计算逻辑错误:
acos()的输入必须是[-1,1]范围内的余弦值,你先将dot/(mag1*mag2)乘以180/pi后再传入acos(),参数范围严重超出合法区间,直接触发nan错误。正确逻辑是acos()先计算得到弧度值,再乘以180/pi转为角度 - 边界情况未处理:如果输入任意一个向量是零向量,
mag1或mag2为0会触发除以0错误,也会返回nan - 函数声明不规范:
find_dotprod_andangled的声明未指定形参类型,依赖C语言老旧的隐式int规则,容易引发未知错误
修正后实现方案(指针返回多值)
修改思路
- 将点积、角度两个变量的指针作为参数传入计算函数,函数内部直接修改对应地址的存储值,无需依赖return带出结果
- 修正角度计算逻辑,先算弧度再转角度
- 增加零向量判断、余弦值范围钳位逻辑,避免非法运算
- 补全函数形参的类型声明
完整可运行代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <math.h> // 新增指针参数:*dot_out存储点积,*angle_deg_out存储角度制夹角 void find_dotprod_andangled(double v1, double v2, double v3, double w1, double w2, double w3, double *dot_out, double *angle_deg_out); double find_magnitude(double v1, double v2, double v3); int main(void) { double v1, v2, v3, w1, w2, w3, dot, angle_deg; char a; printf("Enter M/m or magnitude or D/d for the dot product and angle in degrees: "); scanf("%c", &a); if (a == 'M' || a == 'm') { printf("Enter in values for v1, v2, and v3: "); scanf("%lf,%lf,%lf", &v1, &v2, &v3); printf("The magnitude of the vector is: %lf\n", find_magnitude(v1, v2, v3)); } if (a == 'D' || a == 'd') { printf("Enter in vector 1 (format x,y,z): "); scanf("%lf,%lf,%lf", &v1, &v2, &v3); printf("Enter in vector 2 (format x,y,z): "); scanf("%lf,%lf,%lf", &w1, &w2, &w3); // 传入变量地址接收结果 find_dotprod_andangled(v1, v2, v3, w1, w2, w3, &dot, &angle_deg); printf("The dot product of the vectors is: %lf\n", dot); printf("The angle between vectors (degrees) is: %lf\n", angle_deg); } return 0; } double find_magnitude(double v1, double v2, double v3) { return sqrt(pow(v1, 2) + pow(v2, 2) + pow(v3, 2)); } void find_dotprod_andangled(double v1, double v2, double v3, double w1, double w2, double w3, double *dot_out, double *angle_deg_out) { double mag1, mag2, theta_rad, cos_val; const double pi = 3.14159265359; mag1 = find_magnitude(v1, v2, v3); mag2 = find_magnitude(w1, w2, w3); *dot_out = (v1 * w1) + (v2 * w2) + (v3 * w3); // 零向量判断,避免非法运算 if (mag1 == 0 || mag2 == 0) { *angle_deg_out = 0.0; // 零向量夹角无意义,可根据需求修改返回值 return; } // 限制余弦值范围在[-1,1],避免浮点精度误差导致acos出nan cos_val = *dot_out / (mag1 * mag2); if (cos_val > 1.0) cos_val = 1.0; if (cos_val < -1.0) cos_val = -1.0; // 先算弧度再转角度 theta_rad = acos(cos_val); *angle_deg_out = theta_rad * (180.0 / pi); }
内容的提问来源于stack exchange,提问作者user393
相关产品推荐
相关产品推荐

