Comment puis-je obtenir un nombre aléatoire dans Kotlin?

151

Une méthode générique qui peut renvoyer un entier aléatoire entre 2 paramètres comme le fait ruby ​​avec rand(0..n).

Toute suggestion?

Yago Azedias
la source

Réponses:

374

Ma suggestion serait une fonction d' extension sur IntRange pour créer des aléas comme ceci:(0..10).random()

TL; DR Kotlin> = 1,3, un aléatoire pour toutes les plates-formes

Depuis la version 1.3, Kotlin est livré avec son propre générateur aléatoire multi-plateforme. Il est décrit dans ce KEEP . L'extension décrite ci-dessous fait maintenant partie de la bibliothèque standard Kotlin , utilisez-la simplement comme ceci:

val rnds = (0..10).random()

Kotlin <1,3

Avant 1.3, sur la JVM on utilise Randomou même ThreadLocalRandomsi on est sur JDK> 1.6.

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

Utilisé comme ceci:

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

Si vous souhaitez que la fonction renvoie uniquement 1, 2, ..., 9( 10non incluse), utilisez une plage construite avec until:

(0 until 10).random()

Si vous travaillez avec JDK> 1.6, utilisez à la ThreadLocalRandom.current()place de Random().

KotlinJs et autres variantes

Pour les kotlinjs et autres cas d'utilisation qui ne permettent pas l'utilisation de java.util.Random, consultez cette alternative .

Voir également cette réponse pour les variations de ma suggestion. Il comprend également une fonction d'extension pour les Chars aléatoires .

s1m0nw1
la source
Je suppose que cela utilise également Java java.util.Random?
Simon Forsberg
@SimonForsberg En effet. J'ai ajouté une autre réponse qui ne l'utilise pas: stackoverflow.com/a/49507413/8073652
s1m0nw1
Il y a aussi une proposition ici pour ajouter un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé (CSPRNG) ici: github.com/Kotlin/KEEP/issues/184
Jonathan Leitschuh
41

Générer un entier aléatoire entre from(inclus) et to(exclusif)

import java.util.Random

val random = Random()

fun rand(from: Int, to: Int) : Int {
    return random.nextInt(to - from) + from
}
Magnus
la source
1
Si vous voulez obtenir quelques Ints aléatoires à distance , vous pouvez utiliser Random # int (size, from, to) à la place dans java-8 .
holi-java
3
Cette solution ne fonctionne pas sur Javascript / Native Kotlin. Peut-être que cela pourrait être cool de créer une méthode plus générique pour ce faire. :)
Valentin Michalak
@ValentinMichalak, vous pouvez essayer celui-ci: stackoverflow.com/a/49507413/8073652
s1m0nw1
31

Depuis kotlin 1.2, vous pouvez écrire:

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

Sachez simplement que c'est un gros O (n), mais pour une petite liste (en particulier des valeurs uniques), tout va bien: D

mutexkid
la source
celui-ci est utile pour kotlin-native
user3471194
11

Vous pouvez créer une fonction d'extension similaire à java.util.Random.nextInt(int)mais qui prend un IntRangeau lieu d'un Intpour sa borne:

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

Vous pouvez maintenant l'utiliser avec n'importe quelle Randominstance:

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

Si vous ne souhaitez pas avoir à gérer votre propre Randominstance, vous pouvez définir une méthode pratique en utilisant, par exemple ThreadLocalRandom.current(),:

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

Vous pouvez maintenant obtenir un entier aléatoire comme vous le feriez dans Ruby sans avoir à déclarer d'abord une Randominstance vous-même:

rand(5..9) // returns 5, 6, 7, or 8
mfulton26
la source
10

Variation possible de mon autre réponse pour les caractères aléatoires

Afin d'obtenir des Chars aléatoires , vous pouvez définir une fonction d'extension comme celle-ci

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 vous travaillez avec JDK> 1.6, utilisez à la ThreadLocalRandom.current() place de Random().

Pour les kotlinjs et autres cas d'utilisation qui ne permettent pas l'utilisation de java.util.Random, cette réponse vous aidera.

Kotlin> = 1.3 support multiplateforme pour Random

Depuis la 1.3, Kotlin est livré avec son propre générateur aléatoire multiplateforme. Il est décrit dans ce KEEP . Vous pouvez désormais utiliser directement l'extension dans le cadre de la bibliothèque standard Kotlin sans la définir:

('a'..'b').random()
s1m0nw1
la source
7

En s'appuyant sur l' excellente réponse @ s1m0nw1, j'ai apporté les modifications suivantes.

  1. (0..n) implique inclusif dans Kotlin
  2. (0 jusqu'à n) implique exclusif dans Kotlin
  3. Utilisez un objet singleton pour l'instance aléatoire (facultatif)

Code:

private object RandomRangeSingleton : Random()

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

Cas de test:

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())
                }
        )
    }
Steven Spungin
la source
5

Exemples aléatoires dans la plage [1, 10]

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

ou en utilisant Java Random

val random2 = Random().nextInt(10) + 1
Andreï
la source
1
Votre première réponse me plaît le plus. C'est un one-liner parfait qui ne nécessite pas d'écrire de fonctions d'extension
Alex Semeniuk
4

Kotlin> = 1.3, support multiplateforme pour Random

Depuis la version 1.3, la bibliothèque standard fournissait un support multi-plateforme pour les aléas, voir cette réponse.

Kotlin <1.3 sur JavaScript

Si vous travaillez avec Kotlin JavaScript et que vous n'avez pas accès à java.util.Random, ce qui suit fonctionnera:

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

Utilisé comme ceci:

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
s1m0nw1
la source
4

Une autre façon d'implémenter la réponse de s1m0nw1 serait d'y accéder via une variable. Non pas que ce soit plus efficace mais cela vous évite d'avoir à taper ().

val ClosedRange<Int>.random: Int
    get() = Random().nextInt((endInclusive + 1) - start) +  start 

Et maintenant, il est accessible en tant que tel

(1..10).random
Quinn
la source
3

Dans Kotlin 1.3, vous pouvez le faire comme

val number = Random.nextInt(limit)
déviant
la source
2

Il n'y a pas de méthode standard pour cela, mais vous pouvez facilement créer la vôtre en utilisant l'un Math.random()ou l' autre ou la classe java.util.Random. Voici un exemple utilisant la Math.random()méthode:

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) })
}

Ceci est un exemple de sortie:

[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
Mahdi AlKhalaf
la source
2

La bibliothèque standard de Kotlin ne fournit pas d'API Random Number Generator. Si vous n'êtes pas dans un projet multiplateforme, il vaut mieux utiliser l'api de la plateforme (toutes les autres réponses à la question parlent de cette solution) .

Mais si vous êtes dans un contexte multiplateforme, la meilleure solution est d'implémenter l'aléatoire par vous-même en kotlin pur pour partager le même générateur de nombres aléatoires entre les plateformes. C'est plus simple pour le développement et les tests.

Pour répondre à ce problème dans mon projet personnel, j'implémente un pur générateur de congruence linéaire Kotlin . LCG est l'algorithme utilisé par java.util.Random. Suivez ce lien si vous souhaitez l'utiliser: https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

Mon objectif de mise en œuvre nextInt(range: IntRange)pour vous;).

Faites attention à mon objectif, LCG est bon pour la plupart des cas d'utilisation (simulation, jeux, etc.) mais ne convient pas à une utilisation cryptographique en raison de la prévisibilité de cette méthode.

Valentin Michalak
la source
Je préfère me fier au code spécifique à la plate-forme plutôt que de créer mon propre algorithme aléatoire. Cela me rappelle un peu le code de java.util.Random, mais il ne correspond pas complètement.
Simon Forsberg
2

Si les numéros que vous souhaitez choisir ne sont pas consécutifs, vous pouvez utiliser random().

Usage:

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

Renvoie l'un des nombres figurant dans la liste.

Willi Mentzel
la source
2

En utilisant une fonction de niveau supérieur, vous pouvez obtenir exactement la même syntaxe d'appel que dans Ruby (comme vous le souhaitez):

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

Usage:

rand(1, 3) // returns either 1, 2 or 3
Willi Mentzel
la source
1

Tout d'abord, vous avez besoin d'un RNG. Dans Kotlin, vous devez actuellement utiliser les plates-formes spécifiques (il n'y a pas de Kotlin intégré). Pour la JVM, c'est java.util.Random. Vous devrez en créer une instance, puis appeler random.nextInt(n).

Mibac
la source
1

Pour obtenir un nombre int aléatoire dans Kotlin, utilisez la méthode suivante :

import java.util.concurrent.ThreadLocalRandom

fun randomInt(rangeFirstNum:Int, rangeLastNum:Int) {
    val randomInteger = ThreadLocalRandom.current().nextInt(rangeFirstNum,rangeLastNum)
    println(randomInteger)
}
fun main() {    
    randomInt(1,10)
}


// Result – random Int numbers from 1 to 9

J'espère que cela t'aides.

Andy Fedoroff
la source
0

Vous pouvez créer une fonction d'extension:

infix fun ClosedRange<Float>.step(step: Float): Iterable<Float> {
    require(start.isFinite())
    require(endInclusive.isFinite())
    require(step.round() > 0.0) { "Step must be positive, was: $step." }
    require(start != endInclusive) { "Start and endInclusive must not be the same"}

    if (endInclusive > start) {
        return generateSequence(start) { previous ->
            if (previous == Float.POSITIVE_INFINITY) return@generateSequence null
            val next = previous + step.round()
            if (next > endInclusive) null else next.round()
        }.asIterable()
    }

    return generateSequence(start) { previous ->
        if (previous == Float.NEGATIVE_INFINITY) return@generateSequence null
        val next = previous - step.round()
        if (next < endInclusive) null else next.round()
    }.asIterable()
}

Valeur flottante ronde:

fun Float.round(decimals: Int = DIGITS): Float {
    var multiplier = 1.0f
    repeat(decimals) { multiplier *= 10 }
    return round(this * multiplier) / multiplier
}

Utilisation de la méthode:

(0.0f .. 1.0f).step(.1f).forEach { System.out.println("value: $it") }

Production:

valeur: 0,0 valeur: 0,1 valeur: 0,2 valeur: 0,3 valeur: 0,4 valeur: 0,5 valeur: 0,6 valeur: 0,7 valeur: 0,8 valeur: 0,9 valeur: 1,0

rodrigosimoesrosa
la source
0

Code source complet. Peut contrôler si les doublons sont autorisés.

import kotlin.math.min

abstract class Random {

    companion object {
        fun string(length: Int, isUnique: Boolean = false): String {
            if (0 == length) return ""
            val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9') // Add your set here.

            if (isUnique) {
                val limit = min(length, alphabet.count())
                val set = mutableSetOf<Char>()
                do { set.add(alphabet.random()) } while (set.count() != limit)
                return set.joinToString("")
            }
            return List(length) { alphabet.random() }.joinToString("")
        }

        fun alphabet(length: Int, isUnique: Boolean = false): String {
            if (0 == length) return ""
            val alphabet = ('A'..'Z')
            if (isUnique) {
                val limit = min(length, alphabet.count())
                val set = mutableSetOf<Char>()
                do { set.add(alphabet.random()) } while (set.count() != limit)
                return set.joinToString("")
            }

            return List(length) { alphabet.random() }.joinToString("")
        }
    }
}
Vincent Sit
la source
0

Chaque fois qu'il y a une situation où vous souhaitez générer une clé ou une adresse mac qui est un nombre hexadécimal ayant des chiffres basés sur la demande de l'utilisateur, et cela aussi en utilisant Android et Kotlin, alors mon code ci-dessous vous aide:

private fun getRandomHexString(random: SecureRandom, numOfCharsToBePresentInTheHexString: Int): String {
    val sb = StringBuilder()
    while (sb.length < numOfCharsToBePresentInTheHexString) {
        val randomNumber = random.nextInt()
        val number = String.format("%08X", randomNumber)
        sb.append(number)
    }
    return sb.toString()
} 
Rupesh Gaud
la source
-1

être super duper))

 fun rnd_int(min: Int, max: Int): Int {
        var max = max
        max -= min
        return (Math.random() * ++max).toInt() + min
    }
Deomin Dmitriy
la source