2016-02-28 63 views
1

我一直在編寫代碼來產生水平直方圖。該程序將用戶輸入的任何數字範圍轉換爲矢量。然後它詢問用戶想要直方圖開始的最低值,以及他們希望每個bin有多大。例如:直方圖程序給出奇怪的輸出C++

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

和計算每個容器中有多少項的函數:

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

我會建議一種不同的方法。進行兩遍,首先計算垃圾箱數量,然後再添加它們,看起來很脆弱,並且容易出錯。看到你試圖找出這種錯誤並不令人驚訝。我認爲你的原始方法太複雜了。正如俗話所說:「你越想要管道,越容易堵塞排水溝」。找到最簡單的方法去做,並且將會有最少的意外和難題來處理。

我認爲在數值上進行一次遍歷,計算每個數值屬於哪個數據庫,並計算每個數據塊的數值數量會更簡單。我們使用一個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 ...就是這樣。 histogram現在是您的直方圖。直方圖[0]現在是第一個分箱中的值的數量,即[lowestValue, lowestValue+binSize),其中還包括小於lowestValue的所有值。直方圖[1]將是爲下一個bin找到的值的數量,依此類推。

現在,您只需遍歷histogram地圖,並生成實際的直方圖。

現在,這裏最棘手的部分是histogram地圖將只包含至少找到1個值的鍵。如果沒有值被放入容器中,則地圖將不包含容器編號。因此,如果第一個bin中沒有值,直方圖[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中插入一對,當您訪問地圖時自動創建0。 – QuentinUK

+0

嘿,謝謝。我的悲觀主義性質總是迫使我決不會認爲某些事情會爲我默認構建。 –

+0

謝謝你的建議!我還沒有真正瞭解地圖,但這絕對看起來簡單得多......我將不得不閱讀一些這方面的內容! – Tom