我正在构建一个设备,通过使用Arduino并在C中写入来检测环境噪声的变化。
因为声音传感器会每秒给我一个声级,我怎么能找到近似的中位数而不存储所有连续数据呢?什么是决定当前环境噪声水平发生变化的最佳方法?
答案 0 :(得分:1)
你想要的是一个叫做移动中位数(非常类似于moving average)。这将是您需要将最后n
个值存储在数组中并计算中位数。
以下是这样的:
int data[5] = {0, 0, 0, 0, 0};
int dataI = 0;
int sortedData[5] = {0, 0, 0, 0, 0};
void pushNewData(int d) {
data[dataI] = d;
dataI++;
if(dataI > 4) {
dataI = 0;
}
}
int median() {
for(int i = 0; i < 5; i++) {
sortedData[i] = data[i];
}
// Use a sorting algorithm here to sort sortedData
return sortedData[3];
}
另一方面,如果要获得数百小时数据的中位数,则必须存储每个数据值。如果这是您的使用案例,我强烈建议您使用平均值。由于平均值只是sum / n
,因此您只能有两个变量并添加它们。当然,您必须考虑溢出。
让我们说你仍然想要一个中位数(例如,如果你担心你的数据不是对称的,或者你担心异常值)。在这种情况下,您可以轻松地构建直方图并使用它来估计中位数。
您可以通过创建一组int来完成此操作。索引0适用于值0-5
,索引2适用于值6-10
,依此类推。 (每个值范围的大小将根据您的设置而有所不同。)每次有新数据点进入时,您都会检查哪个&#34;存储桶&#34; (值范围)该点落入并且您将增加该数组中的相应计数器。
从这些数据中很容易估算出中位数。我们假设你提取了这些数据:
Values 00-05: 1
Values 06-10: 7
Values 11-15: 8
Values 16-20: 2
Values 21-25: 1
Values 26-30: 5
由于n = 24,中位数将是n = 12。第12个数据点将在11-15
范围内,因此您的中位数将在11到15之间。
而不是5的范围,您可以轻松地执行3或1的范围,具有相同的效果。只要注意溢出和内存使用:除了确保不使用太多桶之外,你应该使用unsigned long数组。
答案 1 :(得分:0)
搜索“查找运行中位数”。首先搜索stackoverflow。有许多方法,基于数据的已知特征适用性。
一种简单的方法是创建一个整数数组,比如20个相等范围的元素。在获取每个样本时,将值映射到范围集,并将1添加到该计数器。完成后,可以分析计数器值以计算近似中值。
您可能需要尝试一些不同的方法,以确定哪种方法最适合您。