Реклама

воскресенье, 22 сентября 2013 г.

Генерация случайного числа в заданном диапазоне в Java


Для генерации целого случайного числа в заданном диапазоне от Min до Max, обычно используется следующий паттерн:

Min + (int)(Math.random() * ((Max - Min) + 1))

В Java метод Math.random() генерирует число типа double в диапазоне [0,1). Обратите внимание, что 1 не входит в этот диапазон!
Чтобы получить определенный диапазон значений, сначала нужно умножить на разницу между максимумом и минимумом

Math.random() * ( Max - Min )

Это вернет нам значение в диапазоне [0,Max-Min).
К примеру, если мы хотим получить целые значения [5,10], нам нужно покрыть диапазон в 5 целых(int) значений. То есть:

Math.random() * 5

Данный пример будет генерировать значения в диапазоне [0,5).
Теперь нам нужно сдвинуть этот диапазон, чтобы минимальное значение соответствовало желаемому. Для этого мы просто добавляем значение минимума

Min + (Math.random() * (Max - Min))

Теперь мы получим значение в диапазоне [Min,Max). Продолжая наш пример, это будет [5,10):

5 + (Math.random() * (10 - 5))

Но этот вариант все равно не включает значение Max, и вообще, мы получаем значение типа double. Для того чтобы значение Max тоже входило в допустимый диапазон, нужно прибавить 1 к нашему параметру диапазона (Max - Min) и затем избавиться от дробной части приведением значения к int. Вот так:

Min + (int)(Math.random() * ((Max - Min) + 1))

Теперь то что надо! Случайное целое значение в диапазоне [Min,Max], или как в нашем случае [5,10]:

int rnd = 5 + (int)(Math.random() * ((10 - 5) + 1))

Обратите внимание! Как уже не раз (а два) отмечалось в комментариях, при приведении double к int происходит не математическое округление, а просто отсекается дробная часть:

double a = 2.3;
double b = 2.8;
int i_a = (int) a; // i_a=2
int i_b = (int) b; // i_b=2

Это первая статья из серии "Азы программирования на Java". Следующие статьи:

  1. Varargs в Java
  2. Массивы в Java(скоро)
  3. Перечисления в Java (скоро)
  4. ...

33 комментария:

  1. Спасибо,то что нужно и с хорошим разъяснением)

    ОтветитьУдалить
  2. Благодарю, очень хорошая и полезная статья. =)

    ОтветитьУдалить
  3. Спасибо, очень помогло! А как работает (int)?

    ОтветитьУдалить
    Ответы
    1. Александр, (int) - это оператор приведения типа переменной к типу int. Это можно проделывать и с объектами. Google дал вот такую ссылку - http://www.cyberforum.ru/java-j2se/thread240949.html .
      В нашем случае происходит преобразование типа double (это тип, который возвращает метод Math.random()) в int.
      НО!!! Обратите внимание, что происходит не округление значения, а просто УДАЛЯЕТСЯ дробная часть!

      Удалить
    2. Вот-вот, мои тесты показали тоже самое, я думал, может я что-то не так делаю) еще раз спасибо!

      Удалить
  4. Подскажите пожалуйста, а как быть если я хочу выбрать из своего диапазона? Например если из (80; 1000) или же из (-10; 100) ??

    ОтветитьУдалить
    Ответы
    1. Нет проблем. Я так понимаю, в вашем случае нужен диапазон
      a) [80,1000]
      б) [-10,100]
      Смотрим на нашу функцию:
      Min + (int)(Math.random() * ((Max - Min) + 1))
      Min и Max у нас есть. Подставляем значения и получаем:
      а) int rnd = 80 + (int)(Math.random() * ((1000 - 80) + 1))
      б)int rnd = -10 + (int)(Math.random() * ((100 + 10) + 1)) //как учили в школе, минус на минус дает плюс

      Удалить
    2. Ну или чтоб было красивее было:

      int getRandomVal(int min, int max){
      if(min>max) throw new RuntimeException("Неправильные у вас числа!"); //вопрос на засыпку - а что будет если не проверить?
      return min + (int)(Math.random() * ((max - min) + 1));
      }

      Удалить
  5. Добрый день. Не могу понять почему в выражении ((Max - Min) + 1))
    не происходит увеличение мин. и макс. на единицу? И каким образом +1 включает Макс. и при этом не увеличивает Мин., если можно поподробнее. Спасибо

    ОтветитьУдалить
    Ответы
    1. Добрый день. Исходя из описанной формулы, выражение (Max - Min) + 1 является значением, которое расширяет диапазон возможных значений. Напомню, что в диапазон генерируемых значений методом Math.random() 1 не входит. Таким образом получить Max нам не удастся (при преобразовании в int происходит не округление, а отсечение дробной части). Поэтому диапазон расширяется еще на 1.

      Удалить
    2. Понятно, спасибо. Еще вопрос, нижняя граница в Math.random() также не включается?

      Удалить
    3. Нижняя граница Math.random() как раз равна 0. Результат метода - дробное число (тип double), которое больше или равно 0 и меньше 1.

      Удалить
  6. Этот комментарий был удален автором.

    ОтветитьУдалить
  7. Здравствуйте, зачем нужен число в месте Random(), напр: Random r = new Random(50). Здесь 50 означает диапазон 0-50 включительно или что-то другое?

    ОтветитьУдалить
  8. как указать диапазон чисел от 1 до 12??

    ОтветитьУдалить
  9. Что за путаница?

    1:
    Math.random() * ( Max - Min )
    Это вернет нам значение в диапазоне [0,Max-Min].
    2:
    Math.random() * 5
    Данный пример будет генерировать значения в диапазоне [0,5).

    Может, всё-таки в 1. должно быть так:
    [0,Max-Min) ?

    И, наверное, стоит сказать, что здесь:
    (int)(Math.random() * ((Max - Min) + 1))
    При преобразовании в int из double отсеивается дробная часть, т.е. фактически Math.random() * ((Max - Min) + 1) округляется в меньшую сторону.

    ОтветитьУдалить
    Ответы
    1. Спасибо Вам за комментарий, ошибку в тексте исправил.

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

      Удалить
  10. Привет. Помогите пожалуйста разобраться. Стоит задача написать мини программу про “Русскую рулетку". В револьвере 6ть патронов, то есть минимальное значение 1 макс 6, нужно сгенерировать случайное число и если оно попадет в это диапазон, то игрок труп

    это должно быть так?

    if (math.random()*6) < 1)

    если я правильно поняла то это будте [0;6), то есть мин значение которое включено это 0 а максимальное 5? или 6 которое включено? То есть я ограничела не правильно ((

    запуталась((

    ОтветитьУдалить
    Ответы
    1. Привет. В Вашем случае генератор будет выглядеть так: Math.random()*(7) 7=6+1 то есть Ваш максимум плюс один. Таким образом Вы получите диапазон генерируемых чисел типа double от 0 до 6.9999999... Но при приведении к int получите желаемые [0,6]. Итого Ваш код будет: (int)(Math.random()*7)

      Удалить
  11. А как сделать так, чтобы значения макс и мин вводились и между ними уже рассчитывалось случайное число?

    ОтветитьУдалить
  12. А как можно сделать, чтобы программа загадала число, а потом за коммандой вернулась, и опять загадала рандомное число за теми же критериями и так по кругу неограниченое к-ство раз? (Типо идет out print "хотите ли вы еще одно случайное число?" Я ему "да" и программа поехала заново, нашла мне еще одно случайное число из диапазона и потом снова спросила этот вопрос)

    ОтветитьУдалить
    Ответы
    1. Это натуралом надо быть, мил человек

      Удалить
  13. Спасибо большое, очень выручили!

    Правда, у меня без "+1" верхняя граница генерируется - буду разбираться :)

    ОтветитьУдалить
  14. А как найти случайное значение из переменных numberone и numbertwo?

    ОтветитьУдалить
  15. А как найти случайное значение из переменных numberone и numbertwo, при условии что переменные типа double и изменить их нельзя? Могу исходную программу скинуть. Почта moduleseptember@gmail.com. Очень надеюсь на помощь!

    ОтветитьУдалить
  16. VarangaOfficial - стоимость варанга - самая большая и исчерпывающа подборка фактов. Воспользовавшись нашим ресурсом, вы сможете узнать обстоятельную информацию касательно данного лекарственного средства. Увидеть данные о проведенных клинических тестированиях, прочесть реальные отзывы пользователей и медицинского персонала. Ознакомиться с инструкцией по применению, прочесть особенности и методы работы комплекса, осмыслить, почему крем Варанга настолько эффективен, где можно приобрести оригинальный сертифицированный препарат и, как не нарваться на фальсификат. Мы очень тщательно проверяем размещаемые данные. Предоставляем посетителям нашего онлайн-ресурса сведения, которые были почерпнуты исключительно из надежных источников. Если вы обнаружили признаки развития грибка или же долго и безрезультатно стараетесь излечиться от этого досадного недуга, у нас на сайте вы найдете быстрый и простой способ решения проблемы. Приобщайтесь и живите полноценной, здоровой жизнью. Благодаря нам, все ответы на самые волнующие вопросы, теперь собраны в одном месте на удобной в использовании и высоко информационном ресурсе.

    ОтветитьУдалить