C语言递归实现sin/cos计算器出现#IND0错误求排查
问题分析与修复方案
核心错误点
- 递归基线条件错误:你的
my_sin和my_cos终止条件返回值完全不符合三角函数的近似规则:- 当
|x| < TOL时,sin(x)应近似等于x(而非返回1.0); cos(x)可近似为1 - x²/2(比直接返回1.0精度更高)。
这个错误是导致#IND0(非数值NaN)的主要原因。
- 当
- 未做角度归约:输入弧度值较大时(如360度对应2π≈6.28),递归需要多次除以2才能达到TOL阈值,过程中容易出现数值计算不稳定,甚至溢出。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <math.h> #define M_PI 3.14159265358979323846 #define TOL 0.001 double my_sin(double num); double my_cos(double num); // 角度转弧度 double a_radians(double num) { return num * M_PI / 180; } // 将弧度值归约到[-π, π]范围,利用三角函数周期性减少递归次数 double reduce_radians(double num) { num = fmod(num, 2 * M_PI); if (num > M_PI) { num -= 2 * M_PI; } else if (num < -M_PI) { num += 2 * M_PI; } return num; } double my_sin(double num) { num = reduce_radians(num); if (fabs(num) < TOL) { // 小角度近似:sin(x) ≈ x return num; } else { // 二倍角公式:sin(2θ) = 2sinθcosθ,此处num=2θ,θ=num/2 return 2.0 * my_sin(num / 2.0) * my_cos(num / 2.0); } } double my_cos(double num) { num = reduce_radians(num); if (fabs(num) < TOL) { // 小角度近似:cos(x) ≈ 1 - x²/2 return 1.0 - num*num/2.0; } else { // 二倍角公式:cos(2θ) = cos²θ - sin²θ double cos_half = my_cos(num / 2.0); double sin_half = my_sin(num / 2.0); return cos_half * cos_half - sin_half * sin_half; } } int main() { int graus; double radians, cos_r, sin_r; graus = 0; while (graus <= 360) { printf("%d 度", graus); radians = a_radians(graus); printf("\n%f 弧度", radians); sin_r = my_sin(radians); cos_r = my_cos(radians); printf("\n标准sin值:%f", sin(radians)); printf("\n自定义my_sin值:%.5f", sin_r); printf("\n标准cos值:%f", cos(radians)); printf("\n自定义my_cos值:%.5f\n\n", cos_r); graus += 45; } return 0; }
修复说明
- 修正了递归基线条件的返回值,符合小角度三角函数的近似规则;
- 添加
reduce_radians函数,将输入弧度归约到[-π, π]区间,大幅减少递归次数,避免数值不稳定; - 简化了
main函数中冗余的变量赋值逻辑; - 优化了输出文本的可读性。
修改后,#IND0的NaN问题会消失,自定义函数的计算结果也会与标准库结果高度接近。
内容的提问来源于stack exchange,提问作者Pau Forés
相关产品推荐
相关产品推荐

