直方图程序给出奇怪的输出 C++
histogram program gives strange output C++
我一直在编写代码来生成水平直方图。该程序将用户输入的任意范围的数字转化为一个向量。然后它询问用户他们希望直方图开始的最低值,以及他们希望每个 bin 有多大。例如:
如果 lowestValue = 1
和 binSize = 20
vector 填充了值 {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 之间的值。至少从我的测试来看是这样。这是 运行:
的图像
感谢任何帮助。
我建议采用不同的方法。进行两遍,首先计算 bin 的数量,然后另一遍将它们相加,看起来很脆弱,而且容易出错。看到您试图找出此类错误并不奇怪。我觉得你原来的做法太复杂了。
俗话说"the more you overthink the plumbing, the easier it is to stop up the drain"。找到最简单的方法来做某事,它会有最少的惊喜和陷阱,去处理。
我认为更简单的做法是对值进行单次传递,计算每个值属于哪个 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
现在是您的直方图。直方图 [0] 现在是第一个 bin [lowestValue, lowestValue+binSize)
中值的数量,其中还包括小于 lowestValue
的所有值。 histogram[1] 将是为下一个 bin 找到的值的数量,依此类推。
现在,您只需遍历 histogram
地图,并生成实际的直方图。
现在,这里棘手的部分是 histogram
映射将只包含至少找到 1 个值的键。如果没有任何值被放入 bin,则地图将不包括 bin 编号。因此,如果第一个 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;
}
循环中的代码没有初始化 i
,因此结果充其量是不可预测的。
我一直在编写代码来生成水平直方图。该程序将用户输入的任意范围的数字转化为一个向量。然后它询问用户他们希望直方图开始的最低值,以及他们希望每个 bin 有多大。例如:
如果 lowestValue = 1
和 binSize = 20
vector 填充了值 {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 之间的值。至少从我的测试来看是这样。这是 运行:
的图像感谢任何帮助。
我建议采用不同的方法。进行两遍,首先计算 bin 的数量,然后另一遍将它们相加,看起来很脆弱,而且容易出错。看到您试图找出此类错误并不奇怪。我觉得你原来的做法太复杂了。
俗话说"the more you overthink the plumbing, the easier it is to stop up the drain"。找到最简单的方法来做某事,它会有最少的惊喜和陷阱,去处理。
我认为更简单的做法是对值进行单次传递,计算每个值属于哪个 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
现在是您的直方图。直方图 [0] 现在是第一个 bin [lowestValue, lowestValue+binSize)
中值的数量,其中还包括小于 lowestValue
的所有值。 histogram[1] 将是为下一个 bin 找到的值的数量,依此类推。
现在,您只需遍历 histogram
地图,并生成实际的直方图。
现在,这里棘手的部分是 histogram
映射将只包含至少找到 1 个值的键。如果没有任何值被放入 bin,则地图将不包括 bin 编号。因此,如果第一个 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;
}
循环中的代码没有初始化 i
,因此结果充其量是不可预测的。