随机数Mathematica vs Java

时间:2011-02-12 09:45:04

标签: java random wolfram-mathematica

哪一组更“随机”?

Math.random()for Java或随机Mathematica? Java是蓝色的,Mathematica是红色的。

数字是0到50(51?)Mathematica random vs Java

编辑: 这是Mathematica中生成的直方图。

Java Source(丑陋)

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int i = 0;
        int sum = 0;
        int counter = 0;
        String randomNumberList = " ";
        int c = 0;
        while (c != 50){

            while (i != 7) {
            i = (int) (51 * Math.random());
            sum += i;
            ++counter;
            randomNumberList += " " + i;
            }
        i = 0;
        System.out.print("\n" + randomNumberList);
        ++c;
        }

    }

Mathematica源(output.txt是来自Java的转储)

dataset = ReadList["~/Desktop/output.txt", Number] 
dataset2 = RandomReal [{0, 50}, 50000]
Histogram[{dataset, dataset2}]

[编辑]:当我编写代码时,我只是学习循环。对困惑感到抱歉。现在我制作了一个更干净的版本,它们分布均匀。我猜任意循环结束都有很大的不同。

New mathematica output

新代码:

public class RandomNums {

  public static void main(String[] args) {
    int count = 0;
    for (int i = 0; i <= 50000; i++){
        int j = (int) (50 * Math.random());
        System.out.print(j + " ");
        count++;
        if (count == 50){
            System.out.println("\n");
            count = 0;
        }
     }
  }
}

5 个答案:

答案 0 :(得分:11)

如果这个情节对我有意义,那就是Mathematica的统一随机分布的质量比你所展示的Java中的实现要好得多(我没有声称任何Java实现。另外,作为一个免责声明,而不是开始一场火焰战争,我已经成为J2EE和Mathematica开发人员已有一段时间了,尽管我承认在后者方面有更多经验。

这是争论。你有50000点和50个箱子(直方图条),这表明你每箱大约有1000点。更确切地说,我们可以使用遍历性将50000个均匀分布点的问题转化为50000个独立试验的问题,并询问每个箱中最终得到的平均点数和方差。然后通过二项分布给出任何特定bin最终具有k Npoints点的概率:

enter image description here

对于此,平均值为Npoints/Nbins(当然,这是我们直观的预期),方差为Npoints * (1-1/Nbins)* 1/Nbins ~ Npoints/Nbins = 1000,在我们的情况下(Npoints = 50000, Nbins = 50)。取平方根,我们得到的标准差为sqrt(1000) ~ 32,约为平均值的3%(即1000)。结论是,对于理想的均匀分布,对于给定数量的点和箱,我们应该预期每个箱的偏差均为3%的平均值。从图片来看,这与Mathematica发行给我们的非常相似。 Java分发的个别区间的偏差(再次,这里给出的特定实现)要大得多,并且表明区间之间的相关性以及整体上这种均匀分布的质量差得多。

现在,这是一个“高级别”的论点,我不会详细说明原因。然而,这似乎是合乎逻辑的,因为Mathematica(科学,学术界)的传统目标受众(或至少曾经)在这方面比Java要求更高。也就是说,我毫不怀疑存在许多用于许多统计分布的随机数生成器的优秀Java实现 - 它们不是内置于该语言中的东西,与Mathematica不同。

答案 1 :(得分:3)

不是问题的直接答案......但是,任何想要执行某些@belisarius建议的“假设测试”以回复@Leonid的人都可能会发现以下代码片段可用于尝试离开Mathematica:

Needs["JLink`"]

(* Point to a different JVM if you like... *)
(* ReinstallJava[CommandLine -> "...", ClassPath-> "..."] *)

ClearAll@JRandomInteger
JRandomInteger[max_, n_:1] := JRandomInteger[{0, max}, n]
JRandomInteger[{min_, max_}, n_:1] :=
  JavaBlock[
    Module[{range, random}
    , range = max - min + 1
    ; random = JavaNew["java.util.Random"]
    ; Table[min + random@nextInt[range], {n}]
    ]
  ]

Histogram[
  Through[{JRandomInteger, RandomInteger}[{0, 50}, 50000]]
, ChartLegends->{"Java","Mathematica"}
]

请注意,此代码段使用Random.nextInt()而不是Math.random()来尝试更好地处理棘手的上边界。

答案 2 :(得分:2)

看看here。它处理java.util.Random并显示一些陷阱。如果你想要更实用的(:-))随机性,它还建议使用SecureRandom(更昂贵,更安全)。

答案 3 :(得分:1)

我发现一个非常扁平的分布是可疑的,因为它应该是随机的。

以下代码打印出我希望看到的内容,即随机性导致的出现次数的变化。

Random : min count 933, max count 1089
Random : min count 952, max count 1071
Random : min count 922, max count 1056
Random : min count 936, max count 1083
Random : min count 938, max count 1063
SecureRandom : min count 931, max count 1069
SecureRandom : min count 956, max count 1070
SecureRandom : min count 938, max count 1061
SecureRandom : min count 958, max count 1100
SecureRandom : min count 929, max count 1068
/dev/urandom: min count 937, max count 1093
/dev/urandom: min count 936, max count 1063
/dev/urandom: min count 931, max count 1069
/dev/urandom: min count 941, max count 1068
/dev/urandom: min count 931, max count 1080

代码

import java.io.*; 
import java.security.SecureRandom; 
import java.util.Random;

public class Main {
    public static void main(String... args) throws IOException {
        testRandom("Random ", new Random());
        testRandom("SecureRandom ", new SecureRandom());
        testRandom("/dev/urandom", new DevRandom());
    }

    private static void testRandom(String desc, Random random) {
        for (int n = 0; n < 5; n++) {
            int[] counts = new int[50];
            for (int i = 0; i < 50*1000; i++)
                counts[random.nextInt(50)]++;
            int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
            for (int count : counts) {
                if (min > count) min = count;
                if (max < count) max = count;
            }
            System.out.println(desc+": min count " + min + ", max count " + max);
        }
    }

    static class DevRandom extends Random {
        DataInputStream fis;

        public DevRandom() {
            try {
                fis = new DataInputStream(new BufferedInputStream(new FileInputStream("/dev/urandom")));
            } catch (FileNotFoundException e) {
                throw new AssertionError(e);
            }
        }

        @Override
        protected int next(int bits) {
            try {
                return fis.readInt();
            } catch (IOException e) {
                throw new AssertionError(e);
            }
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            if (fis != null) fis.close();
        }
    } 
 }

答案 4 :(得分:0)

使用正确编写的随机代码:

public static void main(String[] args) {
    String randomNumberList = " ";
    for (int c = 0; c < 50000; ++c) {
        // random integer in the range 0 <= i < 50
        int i = (int) Math.floor(50 * Math.random());
        System.out.print(i + " ");
    }
}

我没有看到你所说的差异

                 *      *                         
  **   * * ** * ***  ** ***  ** *   *  * *   **** 
****** **************** **************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************
**************************************************

生成图表的Python代码:

#!/usr/bin/env python
s = raw_input()
nums = [int(i) for i in s.split()]
bins = dict((n,0) for n in range(50))
for i in nums:
    bins[i] += 1

import itertools
heightdivisor = 50 # tweak this to make the graph taller/shorter
xx = ['*'*(v / heightdivisor) for k,v in bins.items()]
print '\n'.join(reversed([''.join(x) for x in itertools.izip_longest(*xx, fillvalue=' ')]))