You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Welford法的C++标准差计算程序异常:均值与结果排查

Fixing Your Test Score Calculator (Welford's Method Included)

Let's break down exactly what's going wrong in your code, plus implement the required Welford's online algorithm correctly—no arrays needed, just a single pass through the data.

1. Input Logic is Broken (Biggest Culprit!)

Right now, your code is skipping the first score and counting the -1 end marker as a valid grade:

  • You read the first score into grade, then immediately read another score at the start of the loop. That first score never gets added to your sum!
  • When you type -1 to end input, the code still adds it to sum and sumSq, and increments numtests. That's why your average is way off.

2. Standard Deviation Formula is Wrong

Your current calculation has two critical math errors:

  • Misplaced parentheses: The correct sample variance formula is (sumSq - n*avg²)/(n-1), but your code divides only the n*avg² term by n-1—totally messing up the calculation.
  • Missing square root: Standard deviation is the square root of variance, but you never call sqrt() to get the final value!
  • No edge case handling: If you enter 0 or 1 scores, you'll hit a divide-by-zero error.

3. You're Not Using Welford's Method

Your code uses the sum/sum-of-squares approach, but the assignment specifically asks for Welford's online algorithm. This method is better for numerical stability (especially with large datasets) and works in a single pass without storing all data. Here's the core logic:

  • Track the current mean and a running variance accumulator (M2) instead of raw sums.
  • For each new score, update the mean incrementally, then adjust M2 using the difference between the new score and the old/new mean.

Fixed Code (Welford's Method + Correct Input Handling)

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    double grade = 0;
    int numtests = 0;
    double mean = 0.0;
    double M2 = 0.0; // Welford's variance accumulator

    cout << "Enter the test scores. Once finished, enter -1 to end input.\n";
    
    // Only process scores that aren't the end marker (-1)
    while (cin >> grade && grade != -1)
    {
        numtests++;
        double delta = grade - mean;
        mean += delta / numtests;
        double delta2 = grade - mean;
        M2 += delta * delta2;
    }

    cout << "The number of scores: " << numtests << "\n";
    
    // Handle edge cases to avoid crashes/invalid results
    if (numtests == 0)
    {
        cout << "No test scores were entered.\n";
        return 0;
    }

    double average = mean;
    double std_dev;
    if (numtests == 1)
    {
        std_dev = 0.0; // A single score has no meaningful sample standard deviation
    }
    else
    {
        std_dev = sqrt(M2 / (numtests - 1));
    }

    cout << "Average: " << average << "\n";
    cout << "Std. Deviation: " << std_dev << "\n";

    return 0;
}

What Changed?

  • Input Fix: The loop now checks if the input is -1 before processing the score, so the end marker is ignored, and the first score gets counted properly.
  • Welford's Implementation: We track mean and M2 iteratively—no sums, no arrays, just a single pass through the input as required.
  • Edge Cases: We handle empty input and single-score input to avoid crashes and invalid calculations.

内容的提问来源于stack exchange,提问作者Larry the Guy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:42:48