Как правильно расширить интервал [0,1] до [a,b]?

Многие генераторы случайных чисел возвращают плавающие числа от 0 до 1.

Какой лучший и правильный способ получить целые числа между a и b?

5 ответов

Решение

Разделите интервал [0,1] на ячейки B-A+1

Пример А =2, В =5

        [----+----+----+----]
        0    1/4  1/2  3/4  1
Maps to    2    3    4    5

Проблема с формулой

 Int (Rnd() * (B-A+1)) + A

заключается в том, что ваш интервал генерации Rnd() закрыт с обеих сторон, поэтому 0 и 1 являются возможными выходами, и формула дает 6, когда Rnd() равно 1.

В реальном случайном распределении (не псевдо) 1 имеет нулевую вероятность. Я думаю, что достаточно безопасно программировать что-то вроде:

 r=Rnd()
 if r equal 1
     MyInt = B
 else
     MyInt = Int(r * (B-A+1)) + A
 endif

редактировать

Просто быстрый тест в Mathematica:

Определим нашу функцию:

f[a_, b_] :=  If[(r = RandomReal[]) == 1, b, IntegerPart[r (b - a + 1)] + a]

Постройте таблицу с 3 10^5 числами в [1100]:

table = SortBy[Tally[Table[f[1, 100], {300000}]], First]

Проверьте минимум и максимум:

In[137]:= {Max[First /@ table], Min[First /@ table]}

Out[137]= {100, 1}  

Давайте посмотрим распределение:

BarChart[Last /@ SortBy[Tally[Table[f[1, 100], {300000}]], First],
        ChartStyle -> "DarkRainbow"]  

альтернативный текст

X = (Rand() * (B - A)) + A

Ну, а почему бы просто не посмотреть, как Python делает это сам? Читать random.py в вашей установке lib каталог.

После потрошения, чтобы поддержать только поведение random.randint() (что вам нужно) и удалив все проверки ошибок для нецелочисленных или выходящих за пределы аргументов, вы получите:

import random
def randint(start, stop):
    width = stop+1 - start
    return start + int(random.random()*width)

Тестирование:

>>> l = []
>>> for i in range(2000000):
...     l.append(randint(3,6))
...
>>> l.count(3)
499593
>>> l.count(4)
499359
>>> l.count(5)
501432
>>> l.count(6)
499616
>>>

Другой способ взглянуть на это, где r - ваше случайное число в диапазоне от 0 до 1:

(1-r)a + rb

Что касается вашего дополнительного требования, чтобы результат был целым числом, возможно (кроме использования встроенного приведения) оператор модуля может вам помочь. Проверьте этот вопрос и ответ:

Расширить случайный диапазон от 1–5 до 1–7

Если предположить, r_a_b желаемое случайное число между a а также b а также r_0_1 это случайное число между 0 а также 1 следующее должно работать просто отлично:

r_a_b = (r_0_1 * (b-a)) + a
Другие вопросы по тегам