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

时间:2016-02-28 23:44:40

标签: c++ output runtime-error histogram

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

如果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之间的值。至少从我的测试中可以看出。这是一个运行的图像:

program run

感谢任何帮助。

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

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