哪类算法可以减少连续输入流中的误差幅度?

| 机器正在测量并连续给我离散数字,如下所示: 1 2 5 7 8 10 11 12 13 14 18 我们可以说这些测量值可以相差2点,并且每5秒生成一次测量值。我想忽略可能相同的度量 像连续2和3可能是相同的,因为误差范围是2,所以如何对数据进行分区,以便仅获得不同的测量值,但我还想处理测量值不断增加的情况,如下所示: 1 2 3 4 5 6 7 8 9 10 在这种情况下,如果我们继续忽略小于2的连续数字,则可能会丢失实际测量值。 为此有一类算法吗?您将如何解决?
已邀请:
在某些工作中,处理此类问题的标准方法是使用卡尔曼滤波器。 引用维基百科: 其[卡尔曼滤波器]的目的是使用测量 随着时间的推移观察到,包含噪音 (随机变化)和其他 错误,并产生可以 趋于接近真实值 测量值及其 相关的计算值。 滤波器本身很容易实现,但需要校准。
只需删除上一个(保留的)“范围内”的数字即可。它应该简单地工作。 对于不断增加的示例: 保留1,因为在1的范围内将2删除,将3丢弃,因为将其在1范围内,然后将4保留,将5和6丢弃在4的范围内,然后将7保留,依此类推,因此如果它足够大,仍然保持增长趋势(这就是您想要的,对吗? 对于原始示例,结果为1、5、8、11、14、18。
我将有两个队列: 临时队列 最终队列/列表 您的第一个值将进入临时队列和最终列表。输入新值时,请检查新值是否在列表中最后一个值的死区之内。如果是,则将其添加到临时队列。如果没有,则将其添加到最终列表中。如果临时队列的大小在死区之外获得新值之前开始增加,那么一旦您处于死区之外,请检查值是否在整个时间内单调增加或减少。如果它们总是在增加或减少,则将队列的内容添加到最终列表,否则只需将单个新值添加到最终列表。这是它的总要旨。 这是我快速编写的一些代码,这些代码实现了一个类来完成我上面描述的操作:
public class MeasurementsFilter
    {
        private Queue<int> tempQueue = new Queue<int>();
        private List<int> finalList = new List<int>();

        private int deadband;

        public MeasurementsFilter(int deadband)
        {
            this.deadband = deadband;
        }

        public void Reset()
        {
            finalList.Clear();
            tempQueue.Clear();
        }

        public int[] FinalValues()
        {
            return finalList.ToArray();
        }

        public void AddNewValue(int value)
        {
            // if we are just starting then the first value always goes in the list and queue
            if (tempQueue.Count == 0)
            {
                tempQueue.Enqueue(value);
                finalList.Add(value);
            }
            else
            {
                // if the new value is within the deadband of the last value added to the final list
                // then enqueue the value and wait
                if ((tempQueue.Peek() - deadband <= value) && (value <= tempQueue.Peek() + deadband))
                {
                    tempQueue.Enqueue(value);
                }
                // else the new value is outside of the deadband of the last value added to the final list
                else
                {

                    tempQueue.Enqueue(value);

                    if (QueueIsAlwaysIncreasingOrAlwaysDecreasing())
                    {
                        //dequeue first item (we already added it to the list before, but we need it for comparison purposes)
                        int currentItem = tempQueue.Dequeue();

                        while (tempQueue.Count > 0)
                        {
                            // if we are not seeing two in a row of the same (i.e. they are not duplicates of each other)
                            // then add the newest value to the final list
                            if (currentItem != tempQueue.Peek())
                            {
                                currentItem = tempQueue.Dequeue();
                                finalList.Add(currentItem);
                            }
                            // otherwise if we are seeing two in a row (i.e. duplicates)
                            // then discard the value and loop to the next value
                            else
                            {
                                currentItem = tempQueue.Dequeue();
                            }

                        }

                        // add the last item from the final list back into the queue for future deadband comparisons
                        tempQueue.Enqueue(finalList[finalList.Count - 1]);

                    }
                    else
                    {
                        // clear the queue and add the new value to the list and as the starting point of the queue
                        // for future deadband comparisons
                        tempQueue.Clear();
                        tempQueue.Enqueue(value);
                        finalList.Add(value);
                    }


                }
            }
        }

        private bool QueueIsAlwaysIncreasingOrAlwaysDecreasing()
        {
            List<int> queueList = new List<int>(tempQueue);

            bool alwaysIncreasing = true;
            bool alwaysDecreasing = true;

            int tempIncreasing = int.MinValue;
            int tempDecreasing = int.MaxValue;

            int i = 0;

            while ((alwaysIncreasing || alwaysDecreasing) && (i < queueList.Count))
            {
                if (queueList[i] >= tempIncreasing)
                    tempIncreasing = queueList[i];
                else
                    alwaysIncreasing = false;

                if (queueList[i] <= tempDecreasing)
                    tempDecreasing = queueList[i];
                else
                    alwaysDecreasing = false;

                i++;

            }

            return (alwaysIncreasing || alwaysDecreasing);

        }
    }
这是一些可以放入Winform Load事件或单击按钮的测试代码:
int[] values = new int[] { 1, 2, 2, 1, 4, 8, 3, 2, 1, 0, 6 };

            MeasurementsFilter filter = new MeasurementsFilter(2);

            for (int i = 0; i < values.Length; i++)
            {
                filter.AddNewValue(values[i]);
            }


            int[] finalValues = filter.FinalValues();

            StringBuilder printValues = new StringBuilder();

            for (int i = 0; i < finalValues.Length; i++)
            {
                printValues.Append(finalValues[i]);
                printValues.Append(\" \");
            }

            MessageBox.Show(\"The final values are: \" + printValues);

要回复问题请先登录注册