Получить псевдослучайное число с плавающей точкой в ​​закрытом интервале [a, b] - PullRequest
1 голос
/ 23 августа 2011

Я хотел бы знать, как наилучшим образом получить псевдослучайное число с плавающей точкой в ​​закрытом интервале, используя функцию ядра Ruby rand (пожалуйста, не случайный модуль).

В качестве примера я буду использовать закрытый интервал [0,0, 7,7] (оба 0,0 и 7,7 включены в интервал), но любой другой интервал с плавающей запятой также должен быть действительным.

Для интервала [0.0, 7.7] следующее решение недопустимо :

rand * 7.7

Почему?

Если вы позвоните rand без аргументов, вы получите псевдослучайное число с плавающей запятой, большее или равное 0,0 и меньшее 1,0. Так каков диапазон чисел с плавающей запятой, которые могут дать нам предыдущие решения?

rand вернет псевдослучайное число с плавающей точкой в ​​диапазоне [0.0, 0.9999999 ...]

0.0 * 7.7
=> 0.0          # Correct!

0.9999999 * 7.7
=> 7.69999923   # Incorrect!

Интервал не совпадает с [0.0, 7.7].

Кто-нибудь знает элегантное решение этой проблемы?

Спасибо!

Ответы [ 5 ]

4 голосов
/ 23 августа 2011

Существует класс Random, который может делать то, что вы хотите:

generator = Random.new # You need to instance it
generator.rand 0.0..7.7

(в документации указано, что будет учитываться разница между 0.0..7.7 и 0.0 ... 7.7.)

В будущем 1.9.3 вы сможете передать диапазон Kernel#rand и Random.rand (вы уже можете сделать это в предварительной версии).

0 голосов
/ 24 августа 2011

Зачем тебе это? Я не знаю случая, когда это понадобилось бы как истинное число с одинарной или двойной точностью. С другой стороны, существуют реальные случаи, когда вам могут понадобиться числа от 0,0 до 7,7 с шагом 0,1. В этом случае вы можете использовать хорошо зарекомендовавшие себя методы, чтобы перейти от 0 до 77, а затем разделить на 10.

0 голосов
/ 23 августа 2011

Как насчет:

(rand / 0.9999999999999999 ...) * 7.7

Как правило, нормализовать случайное число по максимально возможномуслучайный номер.Таким образом, вы создадите диапазон [0..1].

Однако я не уверен, как получить максимальное число, которое в рубине меньше 1,0.

0 голосов
/ 23 августа 2011

Я бы сделал что-то вроде этого:

Fineness = 2**64
puts rand(Fineness+1)*7.7/Fineness

Всякий раз, когда rand возвращает максимально возможное значение, вы получите Fineness*7.7/Fineness, что в точности равно 7,7 (но я не совсем уверен, что так будет всегда, потому что числа с плавающей точкой неточны).

Пока у Fininess больше битов, чем double на вашем компьютере, то я полагаю, что вы не заметите никакой странности в распределении ваших результатов.

0 голосов
/ 23 августа 2011

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

Вот текст из Википедии

Круглая половина до четности Правило разрыва связи, которое еще менее предвзято, округляется от половины до четности,а именно

Если доля y равна 0,5, то q является четным целым числом, ближайшим к y.Таким образом, например, +23,5 становится +24, +22,5 становится +22, -22,5 становится -22, и -23,5 становится -24.

Этот метод также обрабатывает положительные и отрицательные значения симметрично и поэтому является свободнымобщего смещения, если исходные числа являются положительными или отрицательными с равной вероятностью.Кроме того, для наиболее разумного распределения значений y ожидаемое (среднее) значение округленных чисел, по существу, такое же, как и для исходных чисел, даже если последние все положительные (или все отрицательные).Тем не менее, это правило будет по-прежнему вводить положительное смещение для четных чисел (включая ноль) и отрицательное смещение для нечетных.

Этот вариант метода округления до ближайшего также называется несмещенным округлением (неоднозначнои немного оскорбительно), сходящееся округление, округление статистики, округление Голландии, округление Гаусса или округление банкиров.Это широко используется в бухгалтерии.

Это режим округления по умолчанию, используемый в вычислительных функциях и операторах IEEE 754.

...