¿Cómo puedo obtener un número aleatorio en Kotlin?


Un método genérico que puede devolver un entero aleatorio entre 2 parámetros como lo hace ruby con rand(0..n).

Alguna sugerencia?

Author: s1m0nw1, 2017-08-15

15 answers

Kotlin

Sugiero usar la siguiente función extension en IntRange :

fun IntRange.random() = 
       Random().nextInt((endInclusive + 1) - start) +  start

Y úsalo así: {[17]]}

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()

Si desea que la función solo devuelva 1, 2, ..., 9 (10 exclusivo), utilice una gama construida con until:

(0 until 10).random()

Si está trabajando con JDK > 1.6, use ThreadLocalRandom.current() en lugar de Random().

KotlinJs y otras variaciones

Para kotlinjs y otros casos de uso que no permitir el uso de java.util.Random, ver esta alternativa.

También vea esta respuesta para variaciones de mi sugerencia. También incluye una función de extensión para random Chars.

Kotlin > = 1.3 soporte multiplataforma para Random

A partir de la versión 1.3, Kotlin viene con su propio generador aleatorio multiplataforma. Se describe en este MANTENER. Ahora puede hacer lo siguiente (source):

Random.nextInt(0..10)

La función de extensión puede ser simplificado a lo siguiente en todas las plataformas:

fun IntRange.random() = Random.nextInt(this)
 179
Author: s1m0nw1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 06:31:09

Generar un entero aleatorio entre from (inclusivo) y to (exclusivo)

import java.util.Random

val random = Random()

fun rand(from: Int, to: Int) : Int {
    return random.nextInt(to - from) + from
}
 34
Author: Magnus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 01:07:01

A partir de kotlin 1.2, podrías escribir:

(1..3).shuffled().last()

Solo tenga en cuenta que es grande O (n), pero para una lista pequeña (especialmente de valores únicos) está bien: D

 21
Author: mutexkid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-15 22:59:11

Puede crear un función de extensión similar a java.util.Random.nextInt(int) pero uno que toma un IntRange en lugar de un Int para su límite:

fun Random.nextInt(range: IntRange): Int {
    return range.start + nextInt(range.last - range.start)
}

Ahora puede usar esto con cualquier Random instancia:

val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, or 8

Si no desea tener que administrar su propia instancia Random, puede definir un método de conveniencia utilizando, por ejemplo, ThreadLocalRandom.current():

fun rand(range: IntRange): Int {
    return ThreadLocalRandom.current().nextInt(range)
}

Ahora puede obtener un entero aleatorio como lo haría en Ruby sin tener que hacerlo primero declare una instancia Random usted mismo:

rand(5..9) // returns 5, 6, 7, or 8
 10
Author: mfulton26,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-19 23:21:03

Posible variación de mi otra respuesta para caracteres aleatorios

Para obtener Chars aleatorios, puede definir una función de extensión como esta

fun ClosedRange<Char>.random(): Char = 
       (Random().nextInt(endInclusive.toInt() + 1 - start.toInt()) + start.toInt()).toChar()

// will return a `Char` between A and Z (incl.)
('A'..'Z').random()

Si está trabajando con JDK > 1.6, use ThreadLocalRandom.current() en lugar de Random().

Para kotlinjs y otros casos de uso que no permiten el uso de java.util.Random, esta respuesta ayudará.

 7
Author: s1m0nw1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-27 21:09:43

Construyendo a partir de @s1m0nw1 excelente respuesta Hice los siguientes cambios.

  1. (0..n) implica inclusivo en Kotlin
  2. (0 hasta n) implica exclusiva en Kotlin
  3. Utilice un objeto singleton para la instancia aleatoria (opcional)

Código:

private object RandomRangeSingleton : Random()

fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start

Caso de prueba:

fun testRandom() {
        Assert.assertTrue(
                (0..1000).all {
                    (0..5).contains((0..5).random())
                }
        )
        Assert.assertTrue(
                (0..1000).all {
                    (0..4).contains((0 until 5).random())
                }
        )
        Assert.assertFalse(
                (0..1000).all {
                    (0..4).contains((0..5).random())
                }
        )
    }
 6
Author: Steven Spungin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-10 04:31:10

Ejemplos aleatorios en el rango [1, 10]

val random1 = (0..10).shuffled().last()

O utilizando Java Random

val random2 = Random().nextInt(10) + 1
 4
Author: Andrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-01 15:26:08

Si está trabajando con Kotlin JavaScript y no tienen acceso a java.util.Random, lo siguiente funcionará:

fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()

Usado así:

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
 4
Author: s1m0nw1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 06:31:45

Otra forma de implementar la respuesta de s1m0nw1 sería acceder a ella a través de una variable. No es que sea más eficiente, pero te ahorra tener que escribir ().

var ClosedRange<Int>.random: Int
    get() { return Random().nextInt((endInclusive + 1) - start) +  start }
    private set(value) {}

Y ahora se puede acceder como tal

(1..10).random
 3
Author: Quinn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 02:14:35

Usando una función de nivel superior, puede lograr exactamente la misma sintaxis de llamada que en Ruby (como desee):

fun rand(s: Int, e: Int) = Random().nextInt(e + 1 - s) + s

Uso:

rand(1, 3) // returns either 1, 2 or 3
 2
Author: Willi Mentzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-19 08:45:11

Primero, necesitas un RNG. En Kotlin actualmente necesitas usar los específicos de la plataforma (no hay un Kotlin construido en uno). Para la JVM es java.util.Random. Tendrá que crear una instancia de la misma y luego llamar a random.nextInt(n).

 1
Author: Mibac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 01:02:50

No hay un método estándar que haga esto, pero puede crear fácilmente el suyo propio usando Math.random() o la clase java.util.Random. Aquí hay un ejemplo usando el método Math.random():

fun random(n: Int) = (Math.random() * n).toInt()
fun random(from: Int, to: Int) = (Math.random() * (to - from) + from).toInt()
fun random(pair: Pair<Int, Int>) = random(pair.first, pair.second)

fun main(args: Array<String>) {
    val n = 10

    val rand1 = random(n)
    val rand2 = random(5, n)
    val rand3 = random(5 to n)

    println(List(10) { random(n) })
    println(List(10) { random(5 to n) })
}

Esta es una salida de muestra:

[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
 1
Author: Mahdi Al-Khalaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 06:19:30

Si los números entre los que desea elegir no son consecutivos, puede definir su propia función de extensión en List:

fun List<*>.randomElement() 
    = if (this.isEmpty()) null else this[Random().nextInt(this.size)]

Uso:

val list = listOf(3, 1, 4, 5)
val number = list.randomElement()

Devuelve uno de los números que están en la lista.

 1
Author: Willi Mentzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-19 08:53:22

Kotlin standard lib no proporciona una API de generador de números aleatorios. Si no estás en un proyecto multiplataforma, es mejor usar la api de plataforma (todas las otras respuestas de la pregunta hablan de esta solución).

Pero si estás en un contexto multiplataforma, la mejor solución es implementar random por ti mismo en pure kotlin para compartir el mismo generador de números aleatorios entre plataformas. Es más simple para desarrolladores y pruebas.

Para responder a este problema en mi proyecto personal es implementar un Generador Lineal Congruente Kotlin puro. LCG es el algoritmo utilizado por java.util.Random. Sigue este enlace si quieres usarlo : https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

Mi propósito de implementación nextInt(range: IntRange) para ti;).

Tenga cuidado con mi propósito, LCG es bueno para la mayoría de los casos de uso (simulación, juegos, etc...) pero no es adecuado para el uso criptográfico debido a la previsibilidad de este método.

 1
Author: Valentin Michalak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-11 09:54:18

En Kotlin 1.3 puedes hacerlo como

val number = Random.nextInt(limit)
 0
Author: deviant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-13 14:42:21