Avatar ·

Как получить случайное число в Kotlin? Нужны примеры для Int, Double и Boolean

Всем привет! Я только начал изучать Kotlin и столкнулся с проблемой генерации случайных чисел. В Java я привык использовать `Math.random()` или `Random` класс, но в Kotlin хочется писать более идиоматичный код. Мне нужно генерировать случайные числа в разных ситуациях: 1. Случайное целое число в диапазоне (например, от 1 до 100). 2. Случайное дробное число (Double или Float). 3. Случайное булево значение (true/false). 4. Иногда нужно повторить эксперимент с тем же набором чисел (для тестов). Пробовал писать так: ```kotlin val randomInt = (0..100).random() // это работает? val randomDouble = Math.random() // старо-джавовый способ ``` Но код выглядит кустарно. В документации видел упоминание `kotlin.random.Random`, но не понял, как его правильно использовать. Также слышал, что есть `ThreadLocalRandom` для многопоточности, но это уже для Java. Подскажите, пожалуйста, как правильно генерировать случайные числа в Kotlin? Хочется решения, которое будет: - Кроссплатформенным (JVM, JS, Native). - Безопасным для многопоточности. - Простым для чтения. Заранее спасибо! <<>>

Использование kotlin.random.Random — стандартный и правильный способ

В Kotlin нет необходимости использовать Java-классы напрямую. Стандартная библиотека предоставляет мощный и удобный API для работы со случайными числами через объект kotlin.random.Random. Он работает на всех платформах (JVM, JS, Native) и является потокобезопасным по умолчанию.

Основные методы

  • Random.nextInt() — случайное целое число (весь диапазон Int).
  • Random.nextInt(until: Int) — от 0 (включительно) до until (исключительно).
  • Random.nextDouble() — от 0.0 (включительно) до 1.0 (исключительно).
  • Random.nextFloat() — аналогично, но для Float.
  • Random.nextBoolean() — true или false с вероятностью 50%.

Примеры для ваших задач

import kotlin.random.Random

fun main() {
    // 1. Случайное целое от 1 до 100 (включительно)
    val randomIntInRange = Random.nextInt(1, 101)
    println("Случайное целое (1-100): $randomIntInRange")

    // 2. Случайное Double от 0.0 до 1.0
    val randomDouble = Random.nextDouble()
    println("Случайное Double [0, 1): $randomDouble")

    // 3. Случайное Double в произвольном диапазоне (например, от 5.0 до 10.0)
    val randomDoubleInRange = Random.nextDouble(5.0, 10.0)
    println("Случайное Double (5.0-10.0): $randomDoubleInRange")

    // 4. Случайное булево значение
    val randomBoolean = Random.nextBoolean()
    println("Случайный Boolean: $randomBoolean")

    // 5. Случайное число из диапазона с помощью extension-функции
    val randomFromRange = (10..20).random()
    println("Случайное из диапазона 10..20: $randomFromRange")
}

Воспроизводимые последовательности (для тестов)

Если вам нужно повторять одну и ту же последовательность (например, для отладки), используйте Random(seed: Long). Одинаковый seed даёт одинаковые числа:

val seededRandom = Random(42)
println(seededRandom.nextInt(100)) // Всегда 33 (зависит от версии Kotlin)
println(seededRandom.nextInt(100)) // Всегда 62

Почему это лучше, чем Math.random()?

  • Кроссплатформенность: kotlin.random.Random работает везде, а Math.random() — только на JVM.
  • Безопасность: по умолчанию используется потокобезопасная реализация (в JVM — ThreadLocalRandom).
  • Удобство: встроенные extension-функции для диапазонов ((1..100).random()).
  • Производительность: для JVM оптимизирована под многопоточность.

Важные замечания

  • Метод .random() на пустом диапазоне (например, (5..3).random()) выбросит IllegalArgumentException. Всегда проверяйте, что диапазон не пуст.
  • Для криптографически безопасных случайных чисел (пароли, токены) используйте java.security.SecureRandom на JVM или соответствующие библиотеки для других платформ.
  • Если вам нужен глобальный экземпляр с возможностью сброса, используйте DefaultRandom — это синглтон, который можно переопределить в тестах.

В итоге: забудьте про Math.random() в Kotlin. Используйте kotlin.random.Random — это современно, безопасно и удобно.

<<>>

Альтернативный подход: использование Java-совместимости

Если вы работаете только на JVM и привыкли к старому Java API, Kotlin позволяет использовать его напрямую. Это может быть полезно при миграции с Java или если вам нужны специфические реализации (например, SecureRandom).

import java.util.Random

fun main() {
    val javaRandom = Random()
    println("Java Random Int: ${javaRandom.nextInt(100)}")
    println("Java Random Double: ${javaRandom.nextDouble()}")
    
    // Для криптографической стойкости
    val secureRandom = java.security.SecureRandom()
    val secureBytes = ByteArray(16)
    secureRandom.nextBytes(secureBytes)
    println("Secure bytes: ${secureBytes.joinToString("") { "%02x".format(it) }}")
}

Недостатки Java-подхода

  • Не потокобезопасен: java.util.Random требует внешней синхронизации.
  • Только JVM: не работает на Kotlin/Native или Kotlin/JS.
  • Меньше функциональности: нет удобных extension-функций для диапазонов.

Рекомендация: используйте этот способ только если вам нужен SecureRandom для криптографии. Во всех остальных случаях предпочтительнее kotlin.random.Random.