【问题标题】:histogram program gives strange output C++直方图程序给出奇怪的输出 C++
【发布时间】:2016-02-28 23:44:39
【问题描述】:

我一直在编写代码来生成水平直方图。该程序将用户输入的任何数字范围转换为向量。然后它会询问用户他们希望直方图开始的最低值,以及他们希望每个 bin 有多大。例如:

如果lowestValue = 1binSize = 20 并且向量填充了值{1, 2, 3, 20, 30, 40, 50},它会打印出如下内容:

(bin)   (bars)  (num)(percent)
[ 1-21) ####      4    57%
[21-41) ##        2    28%
[41-61) ##        2    28%

这是执行此操作的大部分代码:

void printHistogram(int lowestValue, int binSize, vector<double> v)
{
    int binFloor = lowestValue, binCeiling = 0;
    int numBins = amountOfBins(binSize, (int)range(v));
    for (int i = 0; i<=numBins; i++)
    {
        binCeiling = binFloor+binSize;
        int amoInBin = amountInBin(v,binFloor, binSize);
        double perInBin = percentInBin(v, amoInBin);
        if (binFloor < 10)
        {
            cout << "[ " << binFloor << '-' << binCeiling << ") " << setw(20) << left << formatBars(perInBin) << ' ' << amoInBin << ' '<< setprecision(4) << perInBin << '%' << endl;
            binFloor += binSize;
        }

        else
        {
            cout << '[' << binFloor << '-' << binCeiling << ") " << setw(20) << left << formatBars(perInBin) << ' ' << amoInBin << ' '<< setprecision(4) << perInBin << '%' << endl;
            binFloor += binSize;
        }
    }
}

以及计算每个 bin 中有多少项的函数:

int amountInBin(vector<double> v, int lowestBinValue, int binSize)
{
     int count = 0;
     for (size_t i; i<v.size(); i++)
     {
         if (v[i] >= lowestBinValue && v[i] < (lowestBinValue+binSize))
             count += 1;
     }
     return count;
}

现在我的问题:

由于某种原因,它没有计算 20-40 之间的值。至少从我的测试中可以看出。这是跑步的图像:

感谢任何帮助。

【问题讨论】:

    标签: c++ output runtime-error histogram


    【解决方案1】:

    我会建议一种不同的方法。做两遍,首先计算箱子的数量,然后再一遍将它们相加,看起来很脆弱,而且容易出错。看到你试图找出这种错误并不奇怪。我觉得你原来的方法太复杂了。

    俗话说“你越想水管,就越容易堵住下水道”。找到做某事的最简单方法,并且处理的意外和陷阱最少。

    我认为对值进行一次传递、计算每个值属于哪个 bin 并计算每个 bin 看到的值的数量会更简单。让我们使用std::map,以 bin 编号为键,其值是每个 bin 中值的数量。

    void printHistogram(int lowestValue, int binSize, const std::vector<double> &v)
    {
        std::map<int, size_t> histogram;
    
        for (auto value:v)
        {
           int bin_number= value < lowestValue ? 0:(value-lowestValue)/binSize;
    
           ++histogram[bin_number];
        }
    

    然后……就是这样。 histogram 现在是您的直方图。 histogram[0] 现在是第一个 bin 中的值的数量,[lowestValue, lowestValue+binSize),其中还包括所有小于 lowestValue 的值。 histogram[1] 将是为下一个 bin 找到的值的数量,依此类推。

    现在,您只需遍历 histogram 映射,并生成您的实际直方图。

    现在,这里的棘手部分是 histogram 映射将只包含至少找到 1 个值的键。如果没有值被放入 bin 中,则地图将不包含 bin 编号。因此,如果第一个 bin 中没有值,则 histogram[0] 甚至都不存在,地图中的第一个值将是向量中最低值的 bin。

    这不是一个很难解决的问题,通过一点点额外的智能迭代地图:

    int next_bin_number=0;
    
    for (auto b=histogram.begin(); b != histogram.end(); b++)
    {
        while (next_bin_number < b->first)
        {
             // next_bin_number had 0 values. Print the histogram row
             // for bin #next_bin_number, showing 0 values in it.
    
             ++next_bin_number;
        }
    
        int n_values=b->second;
    
        // Bin #n_next_number, with n_values, print its histogram row
    
        ++next_bin_number;
    }
    

    【讨论】:

    • 您不必插入一对0,当您访问地图时会自动创建0。
    • 嘿,谢谢。我的悲观本性总是迫使我永远不要假设某些东西会为我默认构建。
    • 感谢您的建议!我还没有真正了解地图,但这看起来肯定要简单得多......我将不得不阅读一些关于此的内容!
    【解决方案2】:

    循环中的代码没有初始化i,所以结果充其量是不可预测的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-27
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      • 2021-07-13
      • 2014-02-04
      • 2020-05-14
      • 1970-01-01
      相关资源
      最近更新 更多