web-dev-qa-db-de.com

Wie bekomme ich eine Zufallszahl in Kotlin?

Eine generische Methode, die eine zufällige Ganzzahl zwischen zwei Parametern zurückgeben kann, wie dies Ruby mit Rand(0..n) tut.

Irgendein Vorschlag?

78
Yago Azedias

Mein Vorschlag wäre eine Erweiterung Funktion auf IntRange , um Random wie folgt zu erstellen: (0..10).random()

TL: DR Kotlin> = 1,3, eine Zufallszahl für alle Plattformen

Kotlin verfügt ab 1.3 über einen eigenen Multi-Plattform-Zufallsgenerator. Es ist in diesem KEEP beschrieben. Die unten beschriebene Erweiterung ist jetzt Teil der Kotlin-Standardbibliothek , verwenden Sie sie einfach wie folgt:

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

Kotlin <1,3

Vor 1.3 verwenden wir in der JVM Random oder sogar ThreadLocalRandom, wenn wir uns auf JDK> 1.6 befinden.

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

So benutzt:

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

Wenn die Funktion nur 1, 2, ..., 9 (10 nicht enthalten) zurückgeben soll, verwenden Sie einen mit until erstellten Bereich: _:

(0 until 10).random()

Wenn Sie mit JDK> 1.6 arbeiten, verwenden Sie ThreadLocalRandom.current() anstelle von Random().

KotlinJs und andere Variationen 

Für kotlinjs und andere Anwendungsfälle, die die Verwendung von Java.util.Random nicht zulassen, siehe diese Alternative .

Siehe auch dieses answer für Variationen meines Vorschlags. Es enthält auch eine Erweiterungsfunktion für zufällige Chars.

231
s1m0nw1

Generiere eine zufällige Ganzzahl zwischen from (inklusive) und to (exklusiv)

import Java.util.Random

val random = Random()

fun Rand(from: Int, to: Int) : Int {
    return random.nextInt(to - from) + from
}
39
Magnus

Ab kotlin 1.2 können Sie schreiben: 

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

Seien Sie sich bewusst, dass es ein großes O (n) ist, aber für eine kleine Liste (insbesondere von eindeutigen Werten) ist es in Ordnung: D

26
mutexkid

Sie können eine extension-Funktion erstellen, die Java.util.Random.nextInt(int) ähnelt, aber eine, die IntRange anstelle einer Int für ihre Begrenzung verwendet:

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

Sie können dies jetzt mit jeder Random Instanz verwenden:

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

Wenn Sie keine eigene Random-Instanz verwalten möchten, können Sie eine Komfortmethode definieren, z. B. ThreadLocalRandom.current() :

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

Jetzt können Sie eine zufällige Ganzzahl wie in Ruby erhalten, ohne vorher eine Random-Instanz deklarieren zu müssen:

Rand(5..9) // returns 5, 6, 7, or 8
10
mfulton26

Mögliche Variation zu meinem andere Antwort für zufällige Zeichen

Um zufällige Chars zu erhalten, können Sie eine Erweiterungsfunktion wie folgt definieren

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

Wenn Sie mit JDK> 1.6 arbeiten, verwenden Sie ThreadLocalRandom.current() anstelle von Random().

Für kotlinjs und andere Anwendungsfälle, die die Verwendung von Java.util.Random nicht zulassen, hilft diese Antwort .

Kotlin> = 1.3 Unterstützung für mehrere Plattformen für Zufall

Kotlin verfügt ab 1.3 über einen eigenen Multiplattform-Zufallsgenerator. Es ist in diesem KEEP beschrieben. Sie können die Erweiterung jetzt direkt als Teil der Kotlin-Standardbibliothek verwenden, ohne sie zu definieren:

('a'..'b').random()
8
s1m0nw1

Aufbauend auf @ s1m0nw1 ausgezeichnete Antwort Ich habe folgende Änderungen vorgenommen.

  1. (0..n) impliziert inklusive in Kotlin
  2. (0 bis n) bedeutet exklusiv in Kotlin
  3. Verwenden Sie ein Einzelobjekt für die Zufallsinstanz (optional).

Code:

private object RandomRangeSingleton : Random()

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

Testfall:

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
Steven Spungin

Zufällige Beispiele im Bereich [1, 10] 

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

oder unter Verwendung von Java Random

val random2 = Random().nextInt(10) + 1
5
Andrey

Kotlin> = 1.3, Unterstützung für mehrere Plattformen für Zufall

Seit 1.3 bietet die Standardbibliothek Unterstützung für mehrere Plattformen für Randoms, siehe this answer.

Kotlin <1.3 bei JavaScript

Wenn Sie mit Kotlin JavaScript arbeiten und keinen Zugriff auf Java.util.Random haben, wird Folgendes funktionieren:

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

So benutzt:

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

Eine andere Möglichkeit, die Antwort von s1m0nw1 zu implementieren, wäre der Zugriff über eine Variable. Das ist zwar nicht effizienter, aber es erspart Ihnen das Tippen von ().

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

Und jetzt ist es als solches zugänglich

(1..10).random
3
Quinn

Mit einer Top-Level-Funktion können Sie genau dieselbe Aufrufsyntax wie in Ruby erzielen (wie Sie möchten):

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

Verwendungszweck:

Rand(1, 3) // returns either 1, 2 or 3
2
Willi Mentzel

Wenn die Nummern, aus denen Sie auswählen möchten, nicht fortlaufend sind, können Sie random() verwenden.

Verwendungszweck:

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

Gibt eine der Zahlen aus der Liste zurück.

1
Willi Mentzel

Zunächst benötigen Sie einen RNG. In Kotlin müssen Sie derzeit die Plattform-spezifischen verwenden (es ist kein Kotlin eingebaut). Für die JVM ist es Java.util.Random . Sie müssen eine Instanz davon erstellen und dann random.nextInt(n) aufrufen.

1
Mibac

Es gibt keine Standardmethode, die dies tut, aber Sie können Ihre eigene Methode mit Math.random() oder der Klasse Java.util.Random erstellen. Hier ist ein Beispiel mit der Math.random() Methode:

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

Dies ist eine Beispielausgabe:

[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
1
Mahdi AlKhalaf

Kotlin standard lib bietet keine Zufallszahlengenerator-API. Wenn Sie sich nicht in einem Multiplattform-Projekt befinden, verwenden Sie die Plattform api (alle anderen Antworten der Frage beziehen sich auf diese Lösung).

Wenn Sie sich jedoch in einem Kontext mit mehreren Plattformen befinden, ist die beste Lösung die Implementierung der Zufallszahlen in reinen Kotlin, um den gleichen Zufallszahlengenerator zwischen den Plattformen zu teilen. Für Entwickler und Tests ist es einfacher.

Um dieses Problem in meinem persönlichen Projekt zu beantworten, implementiere ich einen reinen Kotlin Linear Congruential Generator . LCG ist der von Java.util.Random verwendete Algorithmus. Folgen Sie diesem Link, wenn Sie ihn verwenden möchten: https://Gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

Mein Implementierungszweck nextInt(range: IntRange) für Sie;).

Achten Sie auf meinen Zweck. LCG ist für die meisten Anwendungsfälle geeignet. (Simulation, Spiele usw.), ist jedoch aufgrund der Vorhersagbarkeit dieser Methode nicht für die kryptografische Verwendung geeignet.

1

In Kotlin 1.3 kann man das gerne machen

val number = Random.nextInt(limit)
0
deviant

Sie können eine Erweiterungsfunktion erstellen:

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) [email protected] null
            val next = previous + step.round()
            if (next > endInclusive) null else next.round()
        }.asIterable()
    }

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

Runder Gleitkommawert:

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

Verwendung der Methode:

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

Ausgabe:

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

0

Um eine zufällige Int-Zahl in Kotlin zu erhalten, verwende die folgende Methode :

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

Hoffe das hilft.

0
ARGeo

Sie müssen keine benutzerdefinierten Erweiterungsfunktionen mehr verwenden. IntRange verfügt jetzt über eine random() - Erweiterungsfunktion.

val randomNumber = (0..10).random()
0
Willi Mentzel