Ogólna metoda, która może zwrócić losową liczbę całkowitą między 2 parametrami, tak jak robi to ruby rand(0..n)
.
Jakieś sugestie?
Ogólna metoda, która może zwrócić losową liczbę całkowitą między 2 parametrami, tak jak robi to ruby rand(0..n)
.
Jakieś sugestie?
Odpowiedzi:
Moją sugestią byłaby funkcja rozszerzająca w IntRange do tworzenia takich losów:(0..10).random()
Od 1.3 Kotlin jest wyposażony we własny wieloplatformowy generator losowy. Jest to opisane w tym ZACHOWAJ . Opisane poniżej rozszerzenie jest teraz częścią standardowej biblioteki Kotlin , po prostu użyj go w następujący sposób:
val rnds = (0..10).random()
Przed 1.3 w JVM używamy Random
lub nawet ThreadLocalRandom
jeśli jesteśmy na JDK> 1.6.
fun IntRange.random() =
Random().nextInt((endInclusive + 1) - start) + start
Używane w ten sposób:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Jeśli chcesz, aby funkcja zwracała tylko 1, 2, ..., 9
( 10
nie uwzględniono), użyj zakresu skonstruowanego za pomocą until
:
(0 until 10).random()
Jeśli pracujesz z JDK> 1.6, użyj ThreadLocalRandom.current()
zamiast Random()
.
KotlinJs i inne odmiany
W przypadku kotlinjs i innych przypadków użycia, które nie pozwalają na użycie java.util.Random
, zobacz tę alternatywę .
Zobacz również tę odpowiedź dla odmian mojej sugestii. Zawiera również funkcję rozszerzenia dla losowych Char
s.
Wygeneruj losową liczbę całkowitą z przedziału from
(włącznie) i to
(wyłącznie)
import java.util.Random
val random = Random()
fun rand(from: Int, to: Int) : Int {
return random.nextInt(to - from) + from
}
Int
znaków z zakresu, możesz użyć Random # int (size, from, to) zamiast w java-8 .
Od Kotlin 1.2 można napisać:
(1..3).shuffled().last()
Tylko pamiętaj, że to duże O (n), ale dla małej listy (szczególnie unikalnych wartości) jest w porządku: D
Możesz utworzyć funkcję rozszerzającą podobną do java.util.Random.nextInt(int)
tej, która przyjmuje IntRange
zamiast an Int
dla swojego powiązania:
fun Random.nextInt(range: IntRange): Int {
return range.start + nextInt(range.last - range.start)
}
Możesz teraz użyć tego z dowolną Random
instancją:
val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, or 8
Jeśli nie chcesz zarządzać własną Random
instancją, możesz zdefiniować wygodną metodę, używając na przykład ThreadLocalRandom.current()
:
fun rand(range: IntRange): Int {
return ThreadLocalRandom.current().nextInt(range)
}
Teraz możesz otrzymać losową liczbę całkowitą, tak jak w Rubim, bez konieczności wcześniejszego deklarowania Random
instancji:
rand(5..9) // returns 5, 6, 7, or 8
Możliwa odmiana mojej innej odpowiedzi dla losowych znaków
Aby uzyskać losowe wartości Char
s, możesz zdefiniować taką funkcję rozszerzającą
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()
Jeśli pracujesz z JDK> 1.6, użyj ThreadLocalRandom.current()
zamiast Random()
.
W przypadku kotlinjs i innych przypadków użycia, które nie pozwalają na użycie java.util.Random
, ta odpowiedź pomoże.
Od 1.3 Kotlin jest wyposażony we własny wieloplatformowy generator losowy. Jest to opisane w tym ZACHOWAJ . Możesz teraz bezpośrednio używać rozszerzenia jako części standardowej biblioteki Kotlin bez definiowania go:
('a'..'b').random()
Opierając się na doskonałej odpowiedzi @ s1m0nw1 , wprowadziłem następujące zmiany.
Kod:
private object RandomRangeSingleton : Random()
fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start
Przypadek testowy:
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())
}
)
}
Przykłady losowe w zakresie [1, 10]
val random1 = (0..10).shuffled().last()
lub wykorzystując Java Random
val random2 = Random().nextInt(10) + 1
Od wersji 1.3 biblioteka standardowa zapewnia obsługę wielu platform dla losowych danych, zobacz tę odpowiedź.
Jeśli pracujesz z Kotlin JavaScript i nie masz do niego dostępu java.util.Random
, zadziałają:
fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()
Używane w ten sposób:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Innym sposobem zaimplementowania odpowiedzi s1m0nw1 byłoby uzyskanie do niej dostępu poprzez zmienną. Nie oznacza to, że jest to bardziej wydajne, ale pozwala uniknąć konieczności wpisywania ().
val ClosedRange<Int>.random: Int
get() = Random().nextInt((endInclusive + 1) - start) + start
A teraz można uzyskać do niego dostęp jako taki
(1..10).random
W Kotlin 1.3 możesz to zrobić jak
val number = Random.nextInt(limit)
Nie ma standardowej metody, która to robi, ale możesz łatwo utworzyć własną, używając jednej z nich Math.random()
lub klasy java.util.Random
. Oto przykład wykorzystujący Math.random()
metodę:
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) })
}
Oto przykładowe dane wyjściowe:
[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
Biblioteka standardu Kotlin nie zapewnia interfejsu API generatora liczb losowych. Jeśli nie jesteś w projekcie wieloplatformowym, lepiej skorzystać z api platformy (wszystkie pozostałe odpowiedzi na pytanie mówią o tym rozwiązaniu) .
Ale jeśli pracujesz w kontekście wieloplatformowym, najlepszym rozwiązaniem jest samodzielne zaimplementowanie losowego w czystym kotlinie w celu współdzielenia tego samego generatora liczb losowych między platformami. Programowanie i testowanie jest prostsze.
Aby odpowiedzieć na ten problem w moim osobistym projekcie, wdrażam czysty liniowy generator kongruencyjny Kotlin . LCG to algorytm używany przez java.util.Random
. Kliknij ten link, jeśli chcesz go użyć:
https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4
Mój cel realizacji nextInt(range: IntRange)
dla Ciebie;).
Uważaj na mój cel, LCG jest dobre w większości przypadków użycia (symulacja, gry itp.), Ale nie nadaje się do użytku kryptograficznego ze względu na przewidywalność tej metody.
Jeśli liczby, z których chcesz wybierać, nie są kolejnymi liczbami, możesz użyć random()
.
Stosowanie:
val list = listOf(3, 1, 4, 5)
val number = list.random()
Zwraca jedną z liczb znajdujących się na liście.
Używając funkcji najwyższego poziomu, możesz osiągnąć dokładnie taką samą składnię wywołań jak w Rubim (jak chcesz):
fun rand(s: Int, e: Int) = Random.nextInt(s, e + 1)
Stosowanie:
rand(1, 3) // returns either 1, 2 or 3
Najpierw potrzebujesz RNG. W Kotlinie obecnie musisz korzystać z platform specyficznych dla platformy (nie ma wbudowanego Kotlina). Dla JVM to java.util.Random
. Musisz utworzyć jego instancję, a następnie zadzwonić random.nextInt(n)
.
Aby uzyskać losową liczbę Int w Kotlinie, użyj następującej metody :
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
Mam nadzieję że to pomoże.
Możesz utworzyć funkcję rozszerzenia:
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()
}
Wartość Round Float:
fun Float.round(decimals: Int = DIGITS): Float {
var multiplier = 1.0f
repeat(decimals) { multiplier *= 10 }
return round(this * multiplier) / multiplier
}
Zastosowanie metody:
(0.0f .. 1.0f).step(.1f).forEach { System.out.println("value: $it") }
Wynik:
Wartość: 0,0 Wartość: 0,1 Wartość: 0,2 Wartość: 0,3 Wartość: 0,4 Wartość: 0,5 Wartość: 0,6 Wartość: 0,7 Wartość: 0,8 Wartość: 0,9 Wartość: 1,0
Pełny kod źródłowy. Może kontrolować, czy dozwolone są duplikaty.
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("")
}
}
}
Ilekroć jest sytuacja, w której chcesz wygenerować klucz lub adres mac, który jest liczbą szesnastkową zawierającą cyfry na podstawie żądania użytkownika, a także przy użyciu Androida i Kotlin, mój poniższy kod pomoże ci:
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()
}
być super duperem))
fun rnd_int(min: Int, max: Int): Int {
var max = max
max -= min
return (Math.random() * ++max).toInt() + min
}
java.util.Random
?