哪一组更“随机”?
Math.random()for Java或随机Mathematica? Java是蓝色的,Mathematica是红色的。
数字是0到50(51?)
编辑: 这是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}]
[编辑]:当我编写代码时,我只是学习循环。对困惑感到抱歉。现在我制作了一个更干净的版本,它们分布均匀。我猜任意循环结束都有很大的不同。
新代码:
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;
}
}
}
}
答案 0 :(得分:11)
如果这个情节对我有意义,那就是Mathematica的统一随机分布的质量比你所展示的Java
中的实现要好得多(我没有声称任何Java实现。另外,作为一个免责声明,而不是开始一场火焰战争,我已经成为J2EE和Mathematica开发人员已有一段时间了,尽管我承认在后者方面有更多经验。
这是争论。你有50000点和50个箱子(直方图条),这表明你每箱大约有1000点。更确切地说,我们可以使用遍历性将50000个均匀分布点的问题转化为50000个独立试验的问题,并询问每个箱中最终得到的平均点数和方差。然后通过二项分布给出任何特定bin最终具有k
Npoints
点的概率:
对于此,平均值为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=' ')]))