问题
在如下图所示包含一些噪声的数据队列中如何可以把绿色的(有一个点图片上忘记标了)几个主观认为的最大值最小值筛选出来
思路
简述:定义一个噪声阈值,如果当前比上一次超过噪声阈值才进行更新,如果当前比上一次的变化没超过噪声值记录下来,等到需要更新的时候再进行替换。
状态变量:status
{
−
1
=
处于下降趋势中
0
=
相等情况
1
=
处于上升
v
趋势中
\left\{ \begin{array}{l} -1 = 处于下降趋势中\\ 0 =相等情况\\ 1 = 处于上升v趋势中 \\ \end{array} \right.
⎩
⎨
⎧−1=处于下降趋势中0=相等情况1=处于上升v趋势中
处理逻辑:
{
队列为空:直接放进去第一个数据
不为空且增量大于更新阈值
{
s
t
a
t
u
s
=
0
直接放进去并标记趋势
s
t
a
t
u
s
=
1
说明一直处于增量序列中直接替换尾部最大值并更新上一时刻保存量
s
t
a
t
u
s
=
−
1
说明处于下降序列到上升序列的交替点,更新最小值加入上升序列值并更新
s
t
a
t
u
s
不为空且增量小于更新阈值:根据定义的
s
t
a
t
u
s
趋势对应保存到上一时刻保存量中
\left\{ \begin{array}{l} 队列为空:直接放进去第一个数据 \\ 不为空 且 增量大于更新阈值 \left\{ \begin{array}{l} status = 0直接放进去并标记趋势 \\ status = 1说明一直处于增量序列中直接替换尾部最大值并更新上一时刻保存量\\ status = -1说明处于下降序列到上升序列的交替点,更新最小值加入上升序列值并更新status \end{array} \right.\\ 不为空且增量小于更新阈值:根据定义的status趋势对应保存到上一时刻保存量中 \end{array} \right.
⎩
⎨
⎧队列为空:直接放进去第一个数据不为空且增量大于更新阈值⎩
⎨
⎧status=0直接放进去并标记趋势status=1说明一直处于增量序列中直接替换尾部最大值并更新上一时刻保存量status=−1说明处于下降序列到上升序列的交替点,更新最小值加入上升序列值并更新status不为空且增量小于更新阈值:根据定义的status趋势对应保存到上一时刻保存量中
代码
#include "iostream"
#include "deque"
#include "math.h"
#include "random"
using namespace std;
// 抗噪声的最大值最小值队列
class Anti_Noise_MM_Que
{
public:
double m_noise = 0.15; // 噪声大小
deque<double> m_que;
double last_value; // 上一时刻的值
int status = 0; // 切换状态标志位 如果为0则为一样(初始状态) 1是找最大(上一时刻是MAX) -1是找最小(上一时刻是找MIN)
public:
Anti_Noise_MM_Que(double _noise){
m_noise = _noise;
}
~Anti_Noise_MM_Que(){
}
// 加入队列
void push_back(double _data){
// 为空的情况
if (m_que.empty()){
m_que.push_back(_data);
last_value = _data;
status = 0;
return;
}
// 不为空 且 大于更新阈值的情况
if (abs(_data - m_que.back()) > m_noise){
if(status == 0){ // 上一时刻一样(大概率初始状态)
if(_data - m_que.back() > 0){// 上升趋势
m_que.push_back(_data);
status = 1;
}else{ // 下降趋势
m_que.push_back(_data);
status = -1;
}
last_value = _data;
}
else if(status == -1){ // 上一时刻小
if(_data - m_que.back() > 0){// 上升趋势
// 更新最值
m_que.back() = min(last_value, m_que.back());
m_que.push_back(_data);
last_value = _data;
status = 1;
}else{ // 下降趋势
// 替换最值
m_que.back() = _data;
last_value = _data;
}
}else{ // 上一时刻大
if(_data - m_que.back() > 0){// 维持上升趋势
// 替换最值
m_que.back() = _data;
last_value = _data;
}else{ // 变为下降趋势
// 更新最值
m_que.back() = max(last_value, m_que.back());
m_que.push_back(_data);
last_value = _data;
status = -1;
}
}
}
// 不为空 且 小于更新阈值的情况
else{
if(status == 0){
last_value = _data;
}else if(status == -1){// 下降趋势
last_value = min(last_value, _data);
}else{// 上升趋势
last_value = max(last_value, _data);
}
}
}
// 出队列
};
int main(void){
// 进行测试
vector<double> test_vec;
random_device rnd;
mt19937 rng(rnd());
normal_distribution<double> gaosi(0,1);
for(double i = 0; i < 10; i += 0.08){
double noise = gaosi(rng) * 0.1;
double num = sin(i) + noise;
test_vec.push_back(num);
cout << num << " ";
}
cout << endl;
// 测试
Anti_Noise_MM_Que anMMq(0.3);
for(int i = 0; i < test_vec.size(); ++i){
anMMq.push_back(test_vec[i]);
}
// 打印
for(int i = 0; i < anMMq.m_que.size(); ++i){
std::cout << anMMq.m_que[i] << " ";
}
std::cout << endl;
return 0;
}