Un metodo generico che può restituire un numero intero casuale tra 2 parametri come fa ruby rand(0..n)
.
Qualche suggerimento?
Un metodo generico che può restituire un numero intero casuale tra 2 parametri come fa ruby rand(0..n)
.
Qualche suggerimento?
Risposte:
Il mio suggerimento sarebbe una funzione di estensione su IntRange per creare randoms in questo modo:(0..10).random()
A partire da 1.3, Kotlin viene fornito con un proprio generatore casuale multipiattaforma. È descritto in questo MANTENERE . L'estensione descritta di seguito fa ora parte della libreria standard di Kotlin , semplicemente usala in questo modo:
val rnds = (0..10).random()
Prima della 1.3, su JVM utilizziamo Random
o anche ThreadLocalRandom
se siamo su JDK> 1.6.
fun IntRange.random() =
Random().nextInt((endInclusive + 1) - start) + start
Usato così:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Se si desidera restituire la funzione 1, 2, ..., 9
( 10
non inclusa), utilizzare un intervallo costruito con until
:
(0 until 10).random()
Se lavori con JDK> 1.6, usa ThreadLocalRandom.current()
invece di Random()
.
KotlinJs e altre varianti
Per kotlinjs e altri casi d'uso che non ne consentono l'utilizzo java.util.Random
, vedere questa alternativa .
Inoltre, vedi questa risposta per le variazioni del mio suggerimento. Include anche una funzione di estensione per messaggi casuali Char
.
Genera un numero intero casuale tra from
(compreso) e to
(esclusivo)
import java.util.Random
val random = Random()
fun rand(from: Int, to: Int) : Int {
return random.nextInt(to - from) + from
}
Int
, puoi usare Random # int (size, from, to) invece in java-8 .
A partire da kotlin 1.2, potresti scrivere:
(1..3).shuffled().last()
Basta essere consapevoli che è grande O (n), ma per un piccolo elenco (soprattutto di valori univoci) va bene: D
È possibile creare una funzione di estensione simile a java.util.Random.nextInt(int)
quella che utilizza IntRange
invece di una Int
per il suo limite:
fun Random.nextInt(range: IntRange): Int {
return range.start + nextInt(range.last - range.start)
}
Ora puoi usarlo con qualsiasi Random
istanza:
val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, or 8
Se non si desidera gestire la propria Random
istanza, è possibile definire un metodo di convenienza utilizzando, ad esempio ThreadLocalRandom.current()
:
fun rand(range: IntRange): Int {
return ThreadLocalRandom.current().nextInt(range)
}
Ora puoi ottenere un numero intero casuale come faresti in Ruby senza dover prima dichiarare Random
un'istanza tu stesso:
rand(5..9) // returns 5, 6, 7, or 8
Possibile variazione alla mia altra risposta per caratteri casuali
Per ottenere messaggi casuali Char
, puoi definire una funzione di estensione come questa
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()
Se lavori con JDK> 1.6, usa ThreadLocalRandom.current()
invece di Random()
.
Per kotlinjs e altri casi d'uso che non ne consentono l'utilizzo java.util.Random
, questa risposta sarà di aiuto.
A partire da 1.3, Kotlin viene fornito con un proprio generatore casuale multipiattaforma. È descritto in questo MANTENERE . Ora puoi utilizzare direttamente l'estensione come parte della libreria standard di Kotlin senza definirla:
('a'..'b').random()
Sulla base di @ s1m0nw1 risposta eccellente ho apportato le seguenti modifiche.
Codice:
private object RandomRangeSingleton : Random()
fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start
Caso di prova:
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())
}
)
}
Esempi casuali nell'intervallo [1, 10]
val random1 = (0..10).shuffled().last()
o utilizzando Java Random
val random2 = Random().nextInt(10) + 1
A partire dalla 1.3, la libreria standard ha fornito supporto multipiattaforma per randoms, vedi questa risposta.
Se stai lavorando con Kotlin JavaScript e non hai accesso a java.util.Random
, funzionerà quanto segue:
fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()
Usato così:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Un altro modo di implementare la risposta di s1m0nw1 sarebbe accedervi attraverso una variabile. Non è più efficiente, ma ti evita di dover digitare ().
val ClosedRange<Int>.random: Int
get() = Random().nextInt((endInclusive + 1) - start) + start
E ora è possibile accedervi come tale
(1..10).random
Non esiste un metodo standard che lo faccia ma puoi facilmente crearne uno tuo usando Math.random()
o la classe java.util.Random
. Ecco un esempio usando il Math.random()
metodo:
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) })
}
Questo è un output di esempio:
[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
La libreria standard Kotlin non fornisce l'API del generatore di numeri casuali. Se non fai parte di un progetto multipiattaforma, è meglio utilizzare l'API della piattaforma (tutte le altre risposte alla domanda parlano di questa soluzione) .
Ma se ti trovi in un contesto multipiattaforma, la soluzione migliore è implementare random da solo in kotlin puro per condividere lo stesso generatore di numeri casuali tra piattaforme. È più semplice per sviluppatori e test.
Per rispondere a questo problema nel mio progetto personale, implemento un puro generatore congruenziale lineare Kotlin . LCG è l'algoritmo utilizzato da java.util.Random
. Segui questo link se vuoi usarlo:
https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4
Il mio scopo di implementazione nextInt(range: IntRange)
per te;).
Abbi cura del mio scopo, LCG è buono per la maggior parte dei casi d'uso (simulazione, giochi, ecc ...) ma non è adatto per l'uso crittografico a causa della prevedibilità di questo metodo.
Se i numeri che si desidera scegliere non sono consecutivi, è possibile utilizzare random()
.
Uso:
val list = listOf(3, 1, 4, 5)
val number = list.random()
Restituisce uno dei numeri presenti nell'elenco.
Non è più necessario utilizzare le funzioni di estensione personalizzate. IntRange ora ha una random()
funzione di estensione pronta all'uso .
val randomNumber = (0..10).random()
Utilizzando una funzione di livello superiore, puoi ottenere esattamente la stessa sintassi della chiamata di Ruby (come desideri):
fun rand(s: Int, e: Int) = Random.nextInt(s, e + 1)
Uso:
rand(1, 3) // returns either 1, 2 or 3
Innanzitutto, hai bisogno di un RNG. In Kotlin è attualmente necessario utilizzare quelli specifici della piattaforma (non esiste un Kotlin incorporato in uno). Per la JVM lo è java.util.Random
. Dovrai crearne un'istanza e quindi chiamare random.nextInt(n)
.
Per ottenere un numero Int casuale in Kotlin utilizzare il seguente metodo :
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
Spero che questo ti aiuti.
È possibile creare una funzione di estensione:
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()
}
Valore float rotondo:
fun Float.round(decimals: Int = DIGITS): Float {
var multiplier = 1.0f
repeat(decimals) { multiplier *= 10 }
return round(this * multiplier) / multiplier
}
Metodo di utilizzo:
(0.0f .. 1.0f).step(.1f).forEach { System.out.println("value: $it") }
Produzione:
valore: 0.0 valore: 0.1 valore: 0.2 valore: 0.3 valore: 0.4 valore: 0.5 valore: 0.6 valore: 0.7 valore: 0.8 valore: 0.9 valore: 1.0
Codice sorgente completo. Può controllare se sono consentiti duplicati.
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("")
}
}
}
Ogni volta che c'è una situazione in cui vuoi generare un indirizzo chiave o mac che è un numero esadecimale con cifre basate sulla domanda dell'utente e che anche usando Android e Kotlin, allora il mio codice qui sotto ti aiuta a:
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()
}
essere super duper))
fun rnd_int(min: Int, max: Int): Int {
var max = max
max -= min
return (Math.random() * ++max).toInt() + min
}
java.util.Random
?