2016-02-28 3 views
1

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

если 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

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

ответ

0

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

+0

Ух, я всегда делаю эту простую ошибку .. спасибо! – Tom

1

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

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

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

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

Теперь сложная часть состоит в том, что карта histogram будет содержать только ключи, для которых было найдено не менее 1 значения. Если значение не было сброшено в корзину, карта не будет содержать номер ячейки. Итак, если в первом буфере не было значений, гистограмма [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; 
} 
+0

Вам не нужно вставлять пару с 0, когда вы получаете доступ к карте, автоматически создается 0. – QuentinUK

+0

Хех, спасибо. Моя пессимистическая натура всегда заставляет меня никогда не предполагать, что что-то будет построено по умолчанию для меня. –

+0

Спасибо за этот совет! Я еще не узнал о картах, но это определенно выглядит намного проще ... Мне нужно будет кое-что прочитать об этом! – Tom

Смежные вопросы