Java中的Benford定律 – 如何将数学函数转换为Java

我有一个快速的问题。 我试图在java中制作欺诈检测应用程序,该应用程序将主要基于本福德定律。 本福德的定律非常酷,它基本上可以解释为在一个真实的金融交易中,第一个数字通常是1,2或3,很少是8,9。我无法得到本福德公式翻译成可以用Java运行的代码。

http://www.mathpages.com/home/kmath302/kmath302.htm此链接提供了有关本福德法律及其使用方式的更多信息。

我知道我必须使用java数学类才能使用自然日志function,但我不知道该怎么做。 任何帮助将不胜感激。

非常感谢!!

@Rui已经提到了如何计算概率分布函数,但这对你没有多大帮助。

您想要使用的是Kolmogorov-Smirnov检验或卡方检验 。 两者都用于将数据与已知概率分布进行比较,以确定数据集是否可能/不可能具有该概率分布。

卡方用于离散分布,KS用于连续分布。


对于使用Benford定律的卡方,你只需要创建一个直方图H [N],例如9个区间N = 1,2,… 9,迭代数据集以检查第一个数字以计算样本数量9个非零数字中的每一个(或具有90个分箱的前两个数字)。 然后运行卡方检验以将直方图与预期计数E [N]进行比较。

例如,假设您有100个数据。 E [N]可以根据本福德定律计算:

E[1] = 30.1030 (=100*log(1+1)) E[2] = 17.6091 (=100*log(1+1/2)) E[3] = 12.4939 (=100*log(1+1/3)) E[4] = 9.6910 E[5] = 7.9181 E[6] = 6.6946 E[7] = 5.7992 E[8] = 5.1152 E[9] = 4.5757 

然后计算X 2 = sum((H [k] -E [k])^ 2 / E [k]),并与测试中指定的阈值进行比较。 (这里我们有一个没有参数的固定分布,所以参数个数s = 0和p = s + 1 = 1,并且二进制数n是9,所以自由度的数量= np = 8 *。然后你去你方便的卡地表 ,看看数字是否正常。对于8自由度,置信水平如下:

Χ2> 13.362:数据集仍有10%符合本福德定律

Χ2> 15.507:数据集仍有5%符合本福德定律

Χ2> 17.535:数据集仍然符合本福德定律的2.5%

Χ2> 20.090:数据集仍然符合本福德定律的1%

Χ2> 26.125:数据集仍然符合本福德定律的0.1%

假设您的直方图得到H = [29,17,12,10,8,7,6,5,6],Χ2= 0.5585。 这与预期的分布非常接近。 (也许太近了!)

现在假设您的直方图得到H = [27,16,10,9,5,11,6,5,11],Χ2= 13.89。 该直方图来自符合本福特定律的分布的可能性不到10%。 所以我称这个数据集有问题但不过分。

请注意, 必须选择显着性水平(例如10%/ 5%/等)。 如果你使用10%,那么即使它们没问题,预计真正来自Benford的发行版的每10个数据集中大约有1个会失败。 这是一个判断电话。

看起来Apache Commons Math有一个卡方测试的Java实现:

ChiSquareTestImpl.chiSquare(double[] expected, long[] observed)


*关于自由度= 8的说明:这是有道理的; 你有9个数字,但它们有1个约束,即它们都必须加起来达到数据集的大小,所以一旦你知道了直方图的前8个数字,就可以算出第9个数字。


Kolmogorov-Smirnov实际上更简单(直到我找到一个关于它如何工作的简单陈述,我才意识到这一点)但是适用于连续分布。 该方法的工作方式如下:

  • 您计算概率分布的累积分布函数(CDF)。
  • 您可以计算经验累积分布函数(ECDF),这可以通过将数据集按排序顺序轻松获得。
  • 您会发现D =(近似)两条曲线之间的最大垂直距离。

在此处输入图像描述

让我们更深入地处理本福德定律。

  1. Benford定律的CDF:这只是C = log 10 x,其中x在区间[1,10],即包括1但不包括10.如果你看一下Benford定律的广义forms,可以很容易地看到而不是写它log(1 + 1 / n),把它写成log(n + 1)-log(n) – 换句话说,为了得到每个bin的概率,它们减去log的连续差异( n),所以log(n)必须是CDF

  2. ECDF:拿你的数据集,对每个数字,使符号为正,用科学记数法写,并将指数设置为0.(如果你有一个0的数字,不知道怎么办;这似乎不适合自己对本福德定律的分析。)然后按升序对数字进行排序。 ECDF是任何有效x的数据点数<= x。

  3. 计算每个d [k] = max(CDF(y [k]) – (k-1)/ N,k / N-CDF(y [k])的最大差值D = max(d [k])。

这是一个例子:假设我们的数据集= [3.02,1.99,28.3,47,0.61]。 然后ECDF由排序数组[1.99,2.83,3.02,4.7,6.1]表示,你计算D如下:

 D = max( log10(1.99) - 0/5, 1/5 - log10(1.99), log10(2.83) - 1/5, 2/5 - log10(2.83), log10(3.02) - 2/5, 3/5 - log10(3.02), log10(4.70) - 3/5, 4/5 - log10(4.70), log10(6.10) - 4/5, 5/5 - log10(6.10) ) 

其中= 0.2988(= log10(1.99) – 0)。

最后你必须使用 D统计 – 我似乎无法在线找到任何有信誉的表,但Apache Commons Math有一个KolmogorovSmirnovDistributionImpl.cdf()函数,它将计算出的D值作为输入并告诉你D的概率小于此。 采用1-cdf(D)可能更容易,它告诉你D大于或等于你计算的值的概率:如果这是1%或0.1%,这可能意味着数据不符合本福特定律,但如果它是25%或50%,它可能是一个很好的匹配。

如果我理解正确,你想要Java语法中的Benford公式吗?

 public static double probability(int i) { return Math.log(1+(1/(double) i))/Math.log(10); } 

记得插入一个

 import java.lang.Math; 

包裹申报后。

我觉得很可疑没有人回答这个……> _>

我认为你要找的是这样的:

 for(int i = (int)Math.pow(10, position-1); i <= (Math.pow(10, position)-1); i++) { answer += Math.log(1+(1/(i*10+(double) digit))); } answer *= (1/Math.log(10)));