检测无意义数字的算法

时间:2014-02-09 20:54:59

标签: php math

我正在使用一个应用程序来收集价格数据,并在每次检索数据时产生合理的买卖价格。现在,由于系统如何工作,数字可能会变得很高或太小。我对此无能为力。

现在我的问题是,如果我有一个数字数组,如:

$prices = ['300','312','293','298','1025','12'];

什么是摆脱12和1025的好算法?请注意,较高的数字出现的频率远远高于非常低的数字,因此简单地取平均数不起作用。

我考虑采用整个数组的平均值,循环遍历数组并检查每个项目的差异百分比,并检查它是否低于阈值,但我认为这不会像我想的那样准确。

2 个答案:

答案 0 :(得分:2)

您是否考虑过绝对数字?

如果我理解你是正确的,那么有多个价格表,所以平均有效价格可能会有所不同,可能是1000,有些可能是300左右,就像你的例子一样,我的算法建议将适用于两者。您没有告知价格是否总是与示例中的价格一样接近,如果价格较高,则可能会更高。

我将把答案分为四个部分,第一部分将针对两种情况(价格差异在低值时为低而在高值时为高)。如果价格差异随着平均有效价格的增加而增加,那么第二部分将是有用的。第三部分将是你想如何将它们包装在一起的整个算法。最后一部分将是第一次运行时要做的事情。

第1部分:查找验证处理的值

你说你有这些数字的列表,并且它一直在检索新数据。我建议你做的方法是,如果你相互减去两个数字和绝对值。

例:
300-312 = | 12 |

使用数字12我们可以得出结论,这两个价格都在有效的价格范围内。现在让我们来看另外三个例子,一个是两个值无效,另一个是只有一个无效。

例:
1025至1012年= | 1013 |

我们可以看到1013不是这个列表中的平均价格,因为两者都无效,我们必须根据有效价格测试它们。然后算法将删除它们。

例:
300-12 = | 288 |

我们可以看到288也不是有效价格,算法会删除12。

第2部分:验证价格差异不同的价格

如果你有平均价格差异为400的列表,差异为-50和+50会给你的算法带来错误,因此你需要一种方法以可扩展的方式确定这个,这将确保数字越大,价格差异越大。

如果绝对值高于超过两个数字平均数的20%(或其他数字),则需要进一步验证。

例:
(300 + 312)/ 2 = 306是平均数 306 * 0.2 = 61,2

如果您有最高和最低有效数字的存储值,则可以使用其平均值的20%来确定阈值。
(293 + 312)/ 2 = 302,5
302,5 * 0,2 = 60,5

第3部分:将所有内容包装起来并制作算法

所以你要做的第一件事就是确定每个列表中的数据量,列表数量,以及接收数据的频率,数据量越大,接收数据的次数越多,就会合理地索引您的数据。我建议的方法是,为每个列表保存最高和最低有效数字。如果不是这种情况,您可以跳过此部分并查看第4部分,因为您每次收到新数据时基本上都可以针对整个列表运行算法。

首先将4个值添加到列表,最低价格,最高价格,平均价格和阈值。平均价格是(最高价+最低价)/ 2。在此之后,您可以使用平均价格的百分比来确定价格的阈值,我会建议20%,因为它会产生一个接近您使用的数字的数字,即50,通过将平均数乘以平均数来找到阈值0,2。

根据您的数据,您始终可以选择根据最小值,最大值和新数字((最小+最大+新)/ 2 * 0,2)的平均值的20%来查找阈值,您可以如果差异应该改变,则改变这个计算。

当您收到新号码时,您的算法应根据阈值检查绝对数字 根据新数字的频率,我建议以较低的频率。

ProcessNumber(var value)
{
    if(absoluteValue(MinValue-value)<=MaxValue*0,2) //depending on how many numbers you want to be valid you can change the threshold, by doing this you allow the maximum value to change if the new number is valid but higher than max value
    {
        addNumber(value);
    }
    else
    {
        deleteNumber(value);
    }
}

如果检索新数字的过程经常发生,您可以一次添加两个数字,如果奇数出现1/3次,我建议使用上述方法。

ProcessNumbers(var value1, var value2)
    {
    if(absoluteValue(value1-value2)<=threshold) //if you want the thresholdnumber to be valid too, use less than or equal to
        {
            addnumber(value1); 
            addnumber(value2); 
            return true
        }//If you have a method to add them
    else
        if(checkNumber(value1)) // returns true if valid)
            { //we now know value 1 is valid
                deleteNumber(value2); //because the check was false and we know value1 is valid value2 must be the invalid one
                addNumber(value1);
            }
        else if(checkNumber(value2))
            { //we now know value 2 is valid
                deleteNumber(value1);
                addNumber(value2);
            }
        else
            { //we now know both values are invalid
                deleteNumber(value1);
                deleteNumber(value2);
            }
    }

第4部分:首次运行

首次运行时需要一个算法,如果当前没有无效数字并且您没有跳过,则可以忽略此部分。

对于第一次运行,您应该按照它们所处的阈值将数字分组到已排序的列表中 您一次取两个数字,看看绝对值是否低于阈值。

absolute = value1-value2;
threshold = value1+value2)/2*0.2;
if(absolute<threshold)
    AddToThreshold(threshold,value1,value2);
else
    AddToLater(value1,value2);

AddTolater是一个包含您必须重复检查的值的列表,因为您不知道value1,value2或两个值是否将它们发送到此列表中。
addtothreshold确保如果阈值组的值高于提交的阈值,则值将提交给该组。

现在您应该有一些具有阈值的组,您现在所做的是采用最低组中的最低组并取最高组中的最低组并检查其绝对值是否低于其阈值,然后您可以使用此阈值要确定其他绝对值是否低于此特定阈值并将它们相互排序,让我们列出您的列表,并使用两个有效数字中具有最高绝对数的最低阈值。

阈值:
(293 + 298)/2=295,5*0.2=59,1(这是门槛)

2个有效数字中最高的绝对数字:
293-312 = | 19 |

这成了一个非常长的帖子,我希望它能给你至少一些灵感,虽然如果没有那么多的处理可能没有必要,如果没有那么多的列表,除非你在计划,否则所有这些都可能是一种过度杀伤力可扩展的东西。

祝你好运!

答案 1 :(得分:1)

您所描述的内容称为异常值检测。为此目的进行统计测试。无论如何要注意,没有什么能保证100%的可靠性。 http://en.wikipedia.org/wiki/Outlier#Identifying_outliers