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

C++频率直方图统计代码问题:最大值等于区间上限时计数错误

直方图统计中最大值匹配区间上限的计数错误修复方案

问题分析

你的代码在统计直方图频率时,当数组最大值恰好等于最后一个区间上限时,会出现统计项数量超出划分区间数、最后一个区间计数错误的问题。例如划分10个区间时,实际得到11个统计项,最后一个区间的正确计数应为4,却被拆分为3和1。

根源在于两点:

  1. 浮点数精度误差:class_w是浮点数,多次累加range_top后,实际值会略小于理论上限(比如3.1变成3.099999...),导致最大值被错误判定为超出区间,触发额外的区间推进逻辑。
  2. 循环逻辑缺陷:依赖range_top累加的方式易受精度影响,且处理完所有元素后无条件执行hist.push_back(freq),导致统计项数量失控。

解决方案

推荐使用区间索引直接计算的方式,彻底避免浮点数累加的精度问题,同时确保统计项数量与划分区间数一致。

修改后的代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<float> lengths = {
    2.1, 2.5, 1.8, 2.2, 2.9, 2.0, 1.5, 2.8, 2.3, 2.6,
    3.1, 2.9, 2.7, 1.8, 2.2, 2.4, 1.9, 2.3, 2.0, 2.5};
vector<int> hist;
int divisions;

int main(void)
{
    sort(lengths.begin(), lengths.end());

    cin >> divisions;
    float max_val = lengths.back();
    float class_w = max_val / divisions;
    // 初始化直方图为指定划分数量的0值,确保统计项数量正确
    hist.assign(divisions, 0);

    for (float x : lengths)
    {
        // 计算当前元素所属的区间索引
        int idx = static_cast<int>(x / class_w);
        // 处理最大值刚好等于区间上限的情况,避免索引越界
        if (idx == divisions)
        {
            idx = divisions - 1;
        }
        hist[idx]++;
    }

    // 输出区间上限序列
    for (int i = 1; i <= divisions; ++i)
    {
        cout << class_w * i << " ";
    }
    cout << endl;

    // 输出直方图统计结果
    for (int count : hist)
    {
        cout << count << " ";
    }
    cout << endl;

    // 输出排序后的数组
    for (float y : lengths)
    {
        cout << y << " ";
    }
    cout << endl;

    return 0;
}

关键改进点

  1. 固定统计项数量:通过hist.assign(divisions, 0)初始化直方图,确保统计项数量与划分区间数完全一致,不会出现额外项。
  2. 直接计算区间索引:用x / class_w计算元素所属区间,避免浮点数累加带来的精度误差;对最大值单独处理,防止索引越界。
  3. 逻辑简洁可靠:移除复杂的while循环推进逻辑,代码可读性和稳定性大幅提升。

验证结果

当划分为10时,运行修改后的代码会得到正确的直方图统计结果:0 0 0 0 1 2 4 5 4 4,与预期完全一致。

内容的提问来源于stack exchange,提问作者VALKYRIEiSr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:16:01