C++ for循环未正常递增导致标准差计算错误如何排查
问题现象
用C++编写标准差计算程序时出现逻辑异常:
- 代码可正常编译运行,但
deviation函数返回的标准差值完全不符合预期 - 排查定位到
deviation函数内第21行的for循环未正常执行多轮递增,仅跑完第一次迭代就终止,且循环内的累加逻辑没有对nominator变量产生正确的累加效果
原始问题代码如下:
#include <iostream> #include <cmath> using namespace std; const int SIZE = 6; double nums[SIZE] = { 6,5,43,4,7,9 }; double s; double av; int i; double sum = 0; double average() { // 计算数组平均值 sum = 0; for (i = 0; i < SIZE; i++) { sum += nums[i]; } av = static_cast<double>(sum / (SIZE)); return av; } double deviation() { double nominator; for (i = 0; i < SIZE; i++) { nominator += pow(nums[i] - average(), 2); } double inside = static_cast<double>(sum / SIZE); s = sqrt(inside); return s; } int main() { cout << "Numbers: "; for (i = 0; i < SIZE; i++) { nums[i]; cout << nums[i] << ' '; } cout << endl; cout << "Average: " << average() << endl; cout << "Standard Deviation: " << deviation() << endl; }
故障根因
一共有4处逻辑错误,直接导致计算结果异常:
- 局部变量未初始化:
deviation函数内的nominator是局部栈变量,声明时未赋值初始值0。C++不会自动为局部基本类型变量做零初始化,该变量初始值为栈内存残留的随机垃圾值,累加操作从随机值起步,结果必然错误。 - 全局循环计数器污染:循环变量
i被定义为全局变量,deviation的for循环每次迭代调用average()时,average()内部的循环会复用同一个全局i,执行完后会把i的值修改为SIZE(即6)。等average()返回回到外层循环,执行递增判断时i已经满足i >= SIZE的终止条件,因此外层循环仅能执行第一次迭代就直接退出,根本无法完成6次平方差累加。 - 标准差公式逻辑错误:原代码计算开平方的输入值时,完全没有用到累加得到的平方差
nominator,反而直接拿数组总和sum除以SIZE开平方,完全不符合标准差的计算规则。 - 全局变量滥用:把
s/av/i/sum全部定义为全局变量,不同函数随意修改同一块内存的变量值,非常容易出现逻辑交叉污染,是典型的编码坏实践。
修复方案
- 移除不必要的全局变量,循环计数器、临时计算变量全部改为对应函数内的局部变量,避免跨函数修改
- 声明
nominator时显式初始化为0 - 标准差计算逻辑严格遵循公式:先计算数组平均值,再累加每个元素与平均值差值的平方,将平方和除以数据量后开平方得到总体标准差
- 平均值只需要计算1次,不需要在循环内反复调用
average()重复计算,避免无意义的性能损耗
修复后的可运行代码:
#include <iostream> #include <cmath> using namespace std; const int SIZE = 6; double nums[SIZE] = {6, 5, 43, 4, 7, 9}; double average() { double sum = 0; for (int i = 0; i < SIZE; i++) { sum += nums[i]; } return sum / SIZE; } double deviation(double av) { double nominator = 0; for (int i = 0; i < SIZE; i++) { nominator += pow(nums[i] - av, 2); } return sqrt(nominator / SIZE); } int main() { cout << "Numbers: "; for (int i = 0; i < SIZE; i++) { cout << nums[i] << ' '; } cout << endl; double av = average(); cout << "Average: " << av << endl; cout << "Standard Deviation: " << deviation(av) << endl; return 0; }
内容的提问来源于stack exchange,提问作者Mohammed Al-Khater
相关产品推荐
相关产品推荐

