Генерация случайного числа в диапазоне - PullRequest
7 голосов
/ 07 декабря 2009

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

Я хочу установить случайное число в небольшом диапазоне по обе стороны от 1. Примерами могут быть .98, 1.02, .94, 1.1 и т. Д. Все примеры, которые я нахожу, описывают получение случайного числа между 0 и 100, но как я могу использовать это, чтобы попасть в диапазон, который я хочу?

Язык программирования здесь не имеет большого значения, хотя я использую Pure Data. Может кто-нибудь объяснить, пожалуйста, математику?

Ответы [ 15 ]

15 голосов
/ 07 декабря 2009

Равномерное

Если вы хотите (псевдо-) равномерное распределение (равномерно распределенное) между 0,9 и 1,1, тогда будет работать следующее:

  range = 0.2
  return 1-range/2+rand(100)*range/100

Настройте диапазон соответствующим образом.

Псевдо-нормальный

Если вы хотите нормальное распределение (кривая колокольчика), вам потребуется специальный код, который будет зависеть от языка / библиотеки. Вы можете получить близкое приближение с этим кодом:

sd = 0.1
mean = 1
count = 10
sum = 0
for(int i=1; i<count; i++) 
  sum=sum+(rand(100)-50)
}
normal = sum / count
normal = normal*sd + mean
9 голосов
/ 24 ноября 2012

Вообще говоря, чтобы получить случайное число в диапазоне, вы не получаете число от 0 до 100, вы получаете число от 0 до 1. Однако это несущественно, так как вы можете просто получить число 0 - 1, разделив ваш # на 100 - так что я не буду отрабатывать точку.

Когда вы думаете об этом псевдокоде, вам нужно думать о числе между 0 и 1, которое вы получаете как процент . Другими словами, если у меня есть произвольный диапазон между a и b, то, какой процент пути между двумя конечными точками является точкой, которую я выбрал случайным образом. (Таким образом, случайный результат 0.52 означает 52% расстояния между a и b)

Имея это в виду, рассмотрим проблему следующим образом:

  1. Установите начальную и конечную точки вашего диапазона.

    var min = 0.9;

    var max = 1.1;

  2. Получить случайное число от 0 до 1

    var random = Math.random();

  3. Возьмите разницу между начальной и конечной точками диапазона (b - a)

    var range = max - min;

  4. Умножьте ваше случайное число на разницу

    var adjustment = range * random;

  5. Добавьте обратно минимальное значение.

    var result = min + adjustment;

И, таким образом, вы можете понять значения каждого шага в последовательности:

var min = 0.9;
var max = 1.1;
var random = Math.random();      // random     == 0.52796 (for example)
var range = max - min;           // range      == 0.2
var adjustment = range * random; // adjustment == 0.105592
var result = min + adjustment;   // result     == 1.005592

Обратите внимание, что результат гарантированно будет в пределах вашего диапазона. Минимальное случайное значение равно 0, а максимальное случайное значение равно 1. В этих двух случаях происходит следующее:

var min = 0.9;
var max = 1.1;
var random = Math.random();      // random     == 0.0 (minimum)
var range = max - min;           // range      == 0.2
var adjustment = range * random; // adjustment == 0.0
var result = min + adjustment;   // result     == 0.9 (the range minimum)

var min = 0.9;
var max = 1.1;
var random = Math.random();      // random     == 1.0 (maximum)
var range = max - min;           // range      == 0.2
var adjustment = range * random; // adjustment == 0.2
var result = min + adjustment;   // result     == 1.1 (the range maximum)
6 голосов
/ 07 декабря 2009
return 0.9 + rand(100) / 500.0

или я что-то упустил?

3 голосов
/ 22 ноября 2012

Box-Müller на помощь.

var z2_cached;
function normal_random(mean, variance) {

    if ( z2_cached ) {
            var z2 = z2_cached;
            z2_cached = 0
            return z2 * Math.sqrt(variance) + mean;
    }

    var x1 = Math.random();
    var x2 = Math.random();

    var z1 = Math.sqrt(-2 * Math.log(x1) ) * Math.cos( 2*Math.PI * x2);
    var z2 = Math.sqrt(-2 * Math.log(x1) ) * Math.sin( 2*Math.PI * x2);

    z2_cached = z2;
    return z1 * Math.sqrt(variance) + mean;
}

Используйте со значениями среднего 1 и дисперсии, например 0,01

for ( var i=0; i < 20; i++ ) console.log( normal_random(1, 0.01) );
0.937240893365304
1.072511121460833
0.9950053748909895
1.0034139439164074
1.2319710866884104
0.9834737343090275
1.0363970887198277
0.8706648577217094
1.0882382154101415
1.0425139197341595
0.9438723605883214
0.935894021237943
1.0846400276817076
1.0428213927823682
1.020602499547105
0.9547701472093025
1.2598174560413493
1.0086997644531541
0.8711594789918106
0.9669499056660755

Функция дает ок. нормальное распределение вокруг среднего с заданной дисперсией.

3 голосов
/ 21 ноября 2012

Вы можете построить любое распределение по форме в диапазоне [0,1) путем изменения переменной . В частности, если вы хотите случайное распределение некоторого распределения с кумулятивной функцией распределения F, вы просто заменяете равномерное случайное значение из [0,1) на обратную функцию для желаемого CDF.

Один особый (и, возможно, самый популярный) случай - это нормальное распределение N (0,1). Здесь вы можете использовать преобразование Бокса-Мюллера . Масштабируя его с помощью stdev и добавляя среднее, вы получите нормальное распределение с нужными параметрами.

Вы можете суммировать равномерные случайные числа и получить некоторую аппроксимацию нормального распределения, этот случай рассмотрен Ник Фортескью выше.

Если ваши исходные рандомы являются целыми числами, вы должны сначала создать случайный случай в реальном домене с некоторым известным распределением. Например, равномерное распределение в [0,1) вы можете построить таким образом. Вы получаете первое целое число в диапазоне от 0 до 99, умножаете его на 0,01, получаете второе целое число, умножаете на 0,0001 и прибавляете к первому и так далее. Таким образом, вы получите число 0.XXYYZZ ... Двойная точность составляет около 16 десятичных цифр, поэтому вам нужно 8 случайных чисел для построения двойной равномерной единицы.

3 голосов
/ 07 декабря 2009

Если rand () возвращает вам случайное число от 0 до 100, все что вам нужно сделать:

(rand() / 100) * 2

чтобы получить случайное число от 0 до 2.

Если, с другой стороны, вы хотите диапазон от 0,9 до 1,1, используйте следующее:

0.9 + ((rand() / 100) * 0.2)
2 голосов
/ 07 декабря 2009

Как близко? Вы можете использовать гауссово (нормальное) распределение со средним значением 1 и небольшим стандартным отклонением.

Гауссово подходит, если вы хотите, чтобы числа, близкие к 1, встречались чаще, чем числа, которые немного дальше от 1.

Некоторые языки (, такие как Java ) будут иметь поддержку гауссиан в стандартной библиотеке.

2 голосов
/ 07 декабря 2009

low + (random() / 100) * range

Так, например:

0.90 + (random() / 100) * 0.2

1 голос
/ 24 ноября 2012

Вы ищете случайного нет. от 1 до 2, например 1.1,1.5,1.632 и т. д., если да, то вот простой код Python:

import random
print (random.random%2)+1
1 голос
/ 23 ноября 2012

Rand () уже дает вам случайное число от 0 до 100. Максимально различное случайное число, которое вы можете получить с этим значением, равно 100, таким образом, при условии, что вам нужно до трех десятичных чисел 0.950-1.050 - это диапазон, на который вы будете смотреть .

Распределение может быть достигнуто с помощью

0.95 + ((rand() / 100) 
...