cos函数返回0问题及C++正多边形估算π的新手作业求助
解决C++用正多边形计算π的问题及cos函数返回0的错误
Hey there! 作为编程新手,能尝试用几何方法估算π已经很棒了~ 咱们一步步来解决你的问题:先搞定cos返回0的坑,再写出符合要求的完整程序。
一、为什么你的cos函数返回0?
这个问题90%是因为你传入了角度而不是弧度!C++标准库<cmath>里的cos()函数参数是弧度值,不是我们日常用的角度。比如你如果想算60°的余弦,直接传cos(60)的话,程序会把60当成弧度(约等于3437.7°),这个角度的余弦值接近-0.95;而如果传cos(90)(弧度),对应的角度是约5156.6°,余弦值确实接近0——这就是你遇到的问题!
解决办法:
- 把角度转换成弧度:
弧度 = 角度 × π / 180 - 要使用
M_PI这个常量的话,需要在包含<cmath>之前定义_USE_MATH_DEFINES,否则很多编译器(比如MSVC、GCC)会找不到这个宏:#define _USE_MATH_DEFINES #include <cmath>
不过,在这个π估算程序里,我们可以用递推公式替代直接调用三角函数,这样既避免了角度/弧度的混淆,也能提高计算精度和效率,咱们后面的程序会用这个思路。
二、完整的C++程序实现
下面是符合你需求的代码,我会逐段解释:
#define _USE_MATH_DEFINES #include <iostream> #include <cmath> #include <iomanip> using namespace std; int main() { // 初始化:从正六边形开始(边数n=6) int n = 6; double L_in = 6.0; // 内接正六边形周长(半径=1时,边长=1,周长=6) double C_out = 4 * sqrt(3); // 外接正六边形周长:6 * 2*tan(π/6) = 4√3 // 设置输出精度:保留15位小数,匹配容差1e-15的要求 cout << fixed << setprecision(15); // 输出表头 cout << "边数\t内接多边形周长\t外接多边形周长" << endl; cout << n << "\t" << L_in << "\t" << C_out << endl; int steps = 0; const double eps = 1e-15; while (steps < 30) { // 递推计算2n边形的内接和外接周长(避免三角函数,精度更高) double new_L_in = 2 * sqrt(L_in * C_out / 2); // 几何平均递推 double new_C_out = 2 * L_in * C_out / (L_in + C_out); // 调和平均递推 // 更新边数和周长值 n *= 2; L_in = new_L_in; C_out = new_C_out; steps++; // 输出当前步的结果 cout << n << "\t" << L_in << "\t" << C_out << endl; // 检查停止条件:周长差小于容差则提前终止 if (fabs(C_out - L_in) < eps) { cout << "\n达到容差要求,提前停止计算" << endl; break; } } if (steps == 30) { cout << "\n达到最大步数30,停止计算" << endl; } // 输出最终π的估计范围(周长除以2,因为半径为1时圆周长=2π) cout << "\n最终π的估计范围:[" << L_in / 2 << ", " << C_out / 2 << "]" << endl; return 0; }
代码关键细节解释:
- 初始多边形选择:用正六边形是因为它的内接边长等于半径(半径=1时,周长=6),计算简单且收敛到π的速度较快。
- 递推公式优势:
- 内接周长递推式
L_2n = 2*sqrt(L_n*C_n/2)和外接周长递推式C_2n = 2*L_n*C_n/(L_n+C_n),都是基于几何关系推导的,避免了频繁调用三角函数带来的精度损耗和角度转换错误。
- 内接周长递推式
- 停止条件:循环最多执行30次(对应边数从6倍增到6×2^30,精度足够),或者当内外周长差小于
1e-15时提前停止——此时两个周长已经极度接近,π的估计值精度达标。 - 输出格式:用
fixed和setprecision(15)确保输出15位小数,匹配容差的精度要求,表头清晰,每一行对应当前边数的两组周长。
三、备选方案:用三角函数直接计算
如果你一定要用三角函数实现每一步的周长计算,记得必须传入弧度值,示例代码片段如下:
// 计算n边形的内接周长(半径=1) double L_in = 2 * n * sin(M_PI / n); // 计算n边形的外接周长(半径=1) double C_out = 2 * n * tan(M_PI / n);
这个方法也可行,但递推式的精度和效率会更优。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

