C++ 搜索快速/高效的直方图算法(使用预先指定的箱子)
我在Matlab之外没有做太多的编码,但我需要将我的Matlab代码导出到另一种语言,很可能是C。我的Matlab代码包括一个直方图函数histc(),它将我的输入数据(是双精度的,不是整数)放入一个指定的容器数组中,以形成直方图 我确信我可以拼凑出几个嵌套的循环来生成一个直方图函数,但我需要这个函数速度快,内存少,因为它会被反复访问 为了避免重新发明轮子,有人知道C语言是否有任何现有的直方图函数可供使用,或者是否有人需要这样的东西通常是自己创建的吗 有人知道创建直方图的有效算法吗?伪代码很好 提前感谢。GSL(GNU科学图书馆)包含一个直方图实现 以下是文档:C++ 搜索快速/高效的直方图算法(使用预先指定的箱子),c++,c,algorithm,matlab,histogram,C++,C,Algorithm,Matlab,Histogram,我在Matlab之外没有做太多的编码,但我需要将我的Matlab代码导出到另一种语言,很可能是C。我的Matlab代码包括一个直方图函数histc(),它将我的输入数据(是双精度的,不是整数)放入一个指定的容器数组中,以形成直方图 我确信我可以拼凑出几个嵌套的循环来生成一个直方图函数,但我需要这个函数速度快,内存少,因为它会被反复访问 为了避免重新发明轮子,有人知道C语言是否有任何现有的直方图函数可供使用,或者是否有人需要这样的东西通常是自己创建的吗 有人知道创建直方图的有效算法吗?伪代码很好
下面是一个示例用法:。我用C编写了自己的直方图代码,因为它非常简单,我甚至没有想到要查找库。通常,您只需要创建一个数组来包含所需的存储箱数量[
num_-bins=(int)(max_-val-min_-val+1)
],当遇到每个示例时,您可以除以存储箱数量[bin_-idx=(int)((value-min_-val)/bin_-width);
(其中bin_-width=(max_-val-min_-val)/num-bins
)找到它所属的位置,然后增加bin计数器。这是一种简单、快速、单次传递数据的方法。请检查我上面的算法是否存在边缘情况
您可能会遇到的问题是,您输入的域可能未知。如果您的所有数据都在double
的一小部分范围内,那么在整个double
范围内拥有100个存储箱不会有多大好处。解决方案是对数据进行第一次遍历,以找到范围的最小/最大值。对于这一点,确实没有快速解决方法,大多数库都会预先要求最小/最大值。理想的直方图算法将取决于您希望捕获的范围。通常,任何直方图算法都将如下所示:
const int NSAMPLES = whatever;
double samples[NSAMPLES] = { 1.0, 3.93, 1e30, ... }; // your data set
const int NBUCKETS = 10; // or whatever
int counts[NBUCKETS] = { 0 };
for (int i = 0; i != NSAMPLES; ++i) {
counts[TRANSFER(samples[i])]++;
}
其中TRANSFER()
是将输入映射到bin的函数(第0个或第N个bin映射到“超出适用范围”)
TRANSFER()
的确切实现在很大程度上取决于您的样本的预期分布以及您对细节感兴趣的地方。我见过一些常见的方法:
- 范围[a,b]内的均匀分布(需要线性变换)
- 无符号整数值的对数分布(最好与一些值结合,以快速确定两个或类似值的最近幂)
如果您事先不知道分布情况,那么您就真的无法有一个有效的机制来有效地对它们进行分类:您要么猜测(有偏差的或无信息的结果),要么存储所有内容并在最后进行排序,将其分类到大小相等的存储桶中(性能差)。谢谢Kyle,这非常有用!谢谢Tom,传递函数才是直方图生成的艺术。我的数据可以呈现任何类型的分布,这是事先不知道的,柱状图分块需要有线性间隔的分块。因此,我想我需要保存数据,并在最后找到最大值和最小值。比特旋转黑客链接是格雷蒂猜测编辑引入了错误。假设
num\u bins==2
,max==10
和min==0
例如,这导致bin\u width==5
,然后计算最大值的bin将导致10-0/5==2
。索引2
将导致数组越界错误。这是处理最后一个值的常见问题。我假设整数的解决方案是使用bin\u width=(max-min+1)/num\u bins
。但是您将如何处理浮动?如果您的仓位是按照您指定的定义定义的,那么10在仓位索引2中:[0,5[;[5,10[;…
。可以改进域上界的计算以考虑这一点。