C++浮点运算代码出现异常值,请求排查与修复方案
C++数组越界导致的异常值问题修复
问题代码
#include <iostream> #include <cmath> int main() { int a,b,n; std::cin >> a >> b >> n; double xi[n]; double yi[n]; double h = (b - a + 0.0) / n + 0.0; for (int i = 0; i <= n; ++i) { //filling the arrays xi[i] = a + (h*i); yi[i] = xi[i]*xi[i]*std::acos(0.9*xi[i]); } for (int i = 0; i <= 5; ++i) { //displaying first 5 elements of the arrays std::cout << "x" << i << ": " << xi[i] << "\n"; std::cout << "y" << i << ": " << yi[i] << "\n\n"; } return 0; }
问题现象
输入a=0、b=1、n=10(或10的倍数)时,x0本该为0,实际显示0.451027;尝试强制给xi[0]赋值a后,x0仍为错误值,y0变成9.2684e-315,每次运行都出现该问题。
问题根源
你定义的xi[n]和yi[n]是长度为n的数组,合法下标范围是0到n-1。但填充数组的循环条件是i <= n,当i=n时,xi[n]和yi[n]已经超出数组合法下标范围,属于数组越界访问。
数组越界会破坏栈上的其他数据(比如循环变量i、数组的起始地址标记等),导致后续读取xi[0]时拿到被破坏后的垃圾值,强制赋值也因为栈数据被篡改而无法生效。
修复方案
方案1:调整数组长度
把数组定义改为double xi[n+1];和double yi[n+1];,因为你需要存储0到n共n+1个元素,刚好匹配循环的范围。
方案2:调整循环范围
如果不想修改数组长度,把填充循环的条件改为i < n,但这样会少存储x=b对应的元素,需根据实际需求选择。
修复后代码示例(方案1)
#include <iostream> #include <cmath> int main() { int a,b,n; std::cin >> a >> b >> n; double xi[n+1]; // 调整为n+1长度,适配0~n的下标 double yi[n+1]; double h = (b - a) / static_cast<double>(n); // 显式转换为浮点数除法,省略冗余的+0.0 for (int i = 0; i <= n; ++i) { xi[i] = a + h * i; yi[i] = xi[i] * xi[i] * std::acos(0.9 * xi[i]); } for (int i = 0; i <= 5; ++i) { std::cout << "x" << i << ": " << xi[i] << "\n"; std::cout << "y" << i << ": " << yi[i] << "\n\n"; } return 0; }
额外说明
C标准中不支持变长数组(VLA)(即double xi[n];这种用运行时变量定义长度的数组),这是部分编译器(如GCC)的扩展特性。如果要编写标准C代码,建议用std::vector替代:
#include <vector> // ... std::vector<double> xi(n+1); std::vector<double> yi(n+1);
内容的提问来源于stack exchange,提问作者h-swell
相关产品推荐
相关产品推荐

