简体   繁体   English

直方图程序给出奇怪的输出C ++

[英]histogram program gives strange output C++

I have been writing code to produce a horizontal histogram. 我一直在编写代码以生成水平直方图。 This program takes user input of any range of numbers into a vector. 该程序将用户输入的任意范围的数字输入向量。 Then it asks the user for the lowest value they want the histogram to begin at, and how big they want each bin to be. 然后,它向用户询问他们希望直方图开始的最低值,以及他们希望每个bin的大小。 For example: 例如:

if lowestValue = 1 and binSize = 20 and vector is filled with values {1, 2, 3, 20, 30, 40, 50} it would print something like: 如果lowestValue = 1binSize = 20并且向量用值{1, 2, 3, 20, 30, 40, 50} binSize = 20填充,则它将输出如下内容:

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

Here is most of the code that does so: 这是大多数这样做的代码:

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;
        }
    }
}

and the function that counts how many terms are in each 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;
}

Now my issue: 现在我的问题是:

For some reason, it is not counting values between 20-40. 由于某种原因,它不在20-40之间计数。 At least as far as I can see from my testing. 至少从测试中可以看到。 Here is an image of a run: 这是运行的图像:

程序运行

Any help is appreciated. 任何帮助表示赞赏。

I would suggest a different approach. 我建议使用另一种方法。 Making two passes, first calculating the number of bins, then another pass to add them up, looks fragile, and error-prone. 进行两次通过,首先计算箱的数量,然后进行另一次将它们加起来,看起来很脆弱,并且容易出错。 Not really surprise to see you trying to figure out a bug of this kind. 看到您尝试找出此类错误并不奇怪。 I think your original approach is too complicated. 我认为您的原始方法太复杂了。

As the saying goes "the more you overthink the plumbing, the easier it is to stop up the drain". 俗话说:“您对管道的思考越多,堵塞下水道就越容易”。 Find the simplest way to do something, and it will have the least amount of surprises and gotchas, to deal with. 找到最简单的方法来做某事,这将带来最少的惊喜和陷阱。

I think it's simpler to make a single pass over the values, calculating which bin each value belongs to, and counting the number of values seen per bin. 我认为对这些值进行单次传递,计算每个值属于哪个bin并计算每个bin看到的值数量会更简单。 Let's use a std::map , keyed by bin number, with the value being the number of values in each 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];
    }

And ...that's it. 就是这样。 histogram is now your histogram. histogram现在是您的直方图。 histogram[0] is now the number of values in the first bin, [lowestValue, lowestValue+binSize) , which also includes all values less than lowestValue . histogram [0]现在是第一个bin中的值数[lowestValue, lowestValue+binSize) ,该值还包括所有小于lowestValue值。 histogram[1] will be the number of values found for the next bin, and so on. histogram [1]将是在下一个bin中找到的值的数量,依此类推。

Now, you just have to iterate over the histogram map, and generate your actual histogram. 现在,您只需要遍历histogram ,然后生成实际的直方图即可。

Now, the tricky part here is that the histogram map will only include keys for which at least 1 value was found. 现在,这里最棘手的部分是histogram将仅包含找到至少1个值的键。 If no value was dropped into the bin, the map will not include the bin number. 如果没有值放入箱中,则映射将不包括箱号。 So, if there were no values in the first bin, histogram[0] won't even exist, the first value in the map will be the bin for the lowest value in the vector. 因此,如果第一个bin中没有值,直方图[0]甚至将不存在,则映射中的第一个值将是矢量中最低值的bin。

This isn't such a difficult problem to solve, by iterating over the map with a little bit of extra intelligence: 通过一点点额外的智能遍历地图,这并不是一个很难解决的问题:

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;
}

循环中的代码不会初始化i ,因此结果充其量是不可预测的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM