Я писал код для построения горизонтальной гистограммы. Эта программа принимает пользовательский ввод любого диапазона чисел в вектор. Затем он запрашивает у пользователя наименьшее значение, с которого они хотят, чтобы гистограмма начиналась, и какого размера они хотят, чтобы каждая ячейка была. Например:

Если lowestValue = 1 и binSize = 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;
        }
    }
}

И функция, которая подсчитывает, сколько терминов находится в каждой ячейке:

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

Любая помощь приветствуется.

1
Kenta 29 Фев 2016 в 02:44

2 ответа

Лучший ответ

Код в цикле не инициализирует i, поэтому результаты в лучшем случае непредсказуемы.

0
Pete Becker 29 Фев 2016 в 00:20

Я бы предложил другой подход. Выполнение двух проходов, сначала вычисление количества бункеров, а затем еще один проход для их сложения, выглядит хрупким и подверженным ошибкам. Неудивительно, что вы пытаетесь выяснить подобную ошибку. Я считаю, что ваш исходный подход слишком сложен.

Как говорится, «чем больше вы задумаетесь над сантехникой, тем легче заткнуть сток». Найдите самый простой способ сделать что-то, и в нем будет меньше всего сюрпризов и ошибок.

Я думаю, что проще сделать один проход по значениям, вычисляя, к какому бину принадлежит каждое значение, и подсчитывая количество значений, видимых в каждом бункере. Давайте использовать std::map с ключом по номеру ячейки, значение которого является количеством значений в каждой ячейке.

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 теперь ваша гистограмма. гистограмма [0] теперь - это количество значений в первой ячейке, [lowestValue, lowestValue+binSize), которая также включает все значения меньше, чем lowestValue. histogram [1] будет числом значений, найденных для следующего интервала, и так далее.

Теперь вам просто нужно пройтись по карте histogram и сгенерировать вашу фактическую гистограмму.

Сложность состоит в том, что карта histogram будет включать только те ключи, для которых было найдено хотя бы одно значение. Если в корзину не было сброшено никакого значения, карта не будет включать номер ячейки. Таким образом, если в первом интервале не было значений, гистограмма [0] даже не существовала бы, первое значение на карте будет интервалом для самого низкого значения в векторе.

Это не такая уж сложная проблема, чтобы решить итерирование карты с небольшим дополнительным интеллектом:

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
Sam Varshavchik 29 Фев 2016 в 00:19