Случайные числа Mathematica против Java - PullRequest
1 голос
/ 12 февраля 2011

Какой набор является более "случайным"?

Math.random () для Java или random для Mathematica?Ява синего цвета, Mathematica красным.

числа от 0 до 50 (51?) Mathematica random vs Java

РЕДАКТИРОВАТЬ: это гистограмма, сгенерированная в Mathematica.

JavaSource (безобразно)

    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}]

[EDIT]: я только изучал циклы, когда делал код.Извините за путаницу.Сейчас я сделал более чистую версию, и они примерно одинаково распределены.Я думаю, что окончание произвольного цикла имело большое значение.

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 ]

11 голосов
/ 12 февраля 2011

Если этот график что-то мне подсказывает, это то, что качество равномерного случайного распределения Mathematica намного лучше, чем реализация в Java, которую вы показываете (я не утверждаю, что для любой реализации Java. Также, как отказ от ответственности, и чтобы не начинать пламенную войну, я уже некоторое время являюсь разработчиком J2EE и Mathematica, хотя, по общему признанию, имею больше опыта в последнем).

Вот аргумент. У вас есть 50000 точек и 50 бинов (гистограммы), что говорит о том, что у вас примерно 1000 пунктов на бин. Точнее, мы можем использовать эргодичность, чтобы привести проблему 50000 равномерно распределенных точек к 50000 независимым испытаниям, и спросить, каково среднее число точек, попадающих в каждую ячейку, и дисперсию. Вероятность того, что какой-либо конкретный контейнер окажется с 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.

3 голосов
/ 12 февраля 2011

Не прямой ответ на вопрос ... но любой, кто хочет выполнить некоторые из «проверок гипотез», предложенных @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 голосов
/ 12 февраля 2011

Посмотрите здесь . Он имеет дело с java.util.Random и отображает некоторые ошибки. Он также рекомендует использовать SecureRandom (более дорогой, более безопасный), если вы хотите по-настоящему случайную (:-))

1 голос
/ 12 февраля 2011

Я считаю очень плоское распределение подозрительным, учитывая, что оно должно быть случайным.

Следующий код выводит на экран то, что я ожидал увидеть, а именно: изменение количества случаев из-за случайности.

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();
        }
    } 
 }
0 голосов
/ 20 апреля 2011

С правильно написанным случайным кодом:

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=' ')]))
...