Узагальнений метод, який може повернути випадкове ціле число між двома параметрами, як і рубін rand(0..n)
.
Будь-яка пропозиція?
Узагальнений метод, який може повернути випадкове ціле число між двома параметрами, як і рубін rand(0..n)
.
Будь-яка пропозиція?
Відповіді:
Моєю пропозицією буде функція розширення на IntRange для створення таких рандов :(0..10).random()
Станом на 1.3, Kotlin має власний багатоплатформенний генератор Random. Це описано в цьому KEEP . Описане нижче розширення тепер є частиною стандартної бібліотеки Котліна , просто використовуйте його так:
val rnds = (0..10).random()
До 1.3 в JVM ми використовуємо Random
або навіть ThreadLocalRandom
якщо ми на JDK> 1.6.
fun IntRange.random() =
Random().nextInt((endInclusive + 1) - start) + start
Використовується так:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Якщо ви хотіли, щоб функція поверталася 1, 2, ..., 9
( 10
не включається), використовуйте діапазон, побудований з until
:
(0 until 10).random()
Якщо ви працюєте з JDK> 1.6, використовуйте ThreadLocalRandom.current()
замість Random()
.
KotlinJs та інші варіанти
Для котлінгів та інших випадків використання, які не дозволяють використовувати java.util.Random
, див. Цю альтернативу .
Також дивіться цю відповідь щодо варіантів моєї пропозиції. Він також включає функцію розширення для випадкових Char
s.
Створити випадкове ціле число між from
(включно) та to
(виключно)
import java.util.Random
val random = Random()
fun rand(from: Int, to: Int) : Int {
return random.nextInt(to - from) + from
}
Int
s, ви можете використовувати Random # int (розмір, від, до) замість java-8 .
Станом на kotlin 1.2, ви можете написати:
(1..3).shuffled().last()
Просто пам’ятайте, що це великий O (n), але для невеликого списку (особливо унікальних значень) це добре: D
Ви можете створити функцію розширення, схожу на функцію розширення,java.util.Random.nextInt(int)
але IntRange
замість такої Int
:
fun Random.nextInt(range: IntRange): Int {
return range.start + nextInt(range.last - range.start)
}
Тепер ви можете використовувати це з будь-яким Random
примірником:
val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, or 8
Якщо вам не потрібно керувати власним Random
екземпляром, ви можете визначити метод зручності, використовуючи, наприклад ThreadLocalRandom.current()
:
fun rand(range: IntRange): Int {
return ThreadLocalRandom.current().nextInt(range)
}
Тепер ви можете отримати випадкове ціле число, як у Ruby, не спочатку оголошуючи Random
екземпляр самостійно:
rand(5..9) // returns 5, 6, 7, or 8
Можливий варіант моєї іншої відповіді для випадкових символів
Для отримання випадкових Char
s, ви можете визначити функцію розширення, як це
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()
Якщо ви працюєте з JDK> 1.6, використовуйте ThreadLocalRandom.current()
замість Random()
.
Для kotlinjs та інших випадків використання, які не дозволяють використовувати java.util.Random
, ця відповідь допоможе.
Станом на 1.3, Котлін має власний багатоплатформенний генератор випадкових випадків. Це описано в цьому KEEP . Тепер ви можете безпосередньо використовувати розширення як частину стандартної бібліотеки Котліна, не визначаючи його:
('a'..'b').random()
Будівництво геть @ s1m0nw1 відмінного відповіді я зробив наступні зміни.
Код:
private object RandomRangeSingleton : Random()
fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start
Тестовий випадок:
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())
}
)
}
Приклади випадкових у діапазоні [1, 10]
val random1 = (0..10).shuffled().last()
або використання Java Random
val random2 = Random().nextInt(10) + 1
Станом на 1.3, стандартна бібліотека надала багатоплатформенну підтримку рандомів, див. Цю відповідь.
Якщо ви працюєте з JavaScript Kotlin і не маєте доступу до них java.util.Random
, буде працювати наступне:
fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()
Використовується так:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Іншим способом реалізації відповіді s1m0nw1 було б доступ до неї через змінну. Це не більш ефективно, але це позбавляє вас від необхідності вводити ().
val ClosedRange<Int>.random: Int
get() = Random().nextInt((endInclusive + 1) - start) + start
І тепер до нього можна отримати доступ як такий
(1..10).random
У Kotlin 1.3 ви можете робити так, як
val number = Random.nextInt(limit)
Не існує стандартного методу, який це робить, але ви можете легко створити свій власний, використовуючи Math.random()
або клас, або клас java.util.Random
. Ось приклад використання 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) })
}
Це вибірковий вихід:
[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
Стандартна lib Kotlin не забезпечує API генератора випадкових чисел. Якщо ви не є багатоплатформою, краще скористатися платформою api (всі інші відповіді на питання говорять про це рішення) .
Але якщо ви перебуваєте в мультиплатформенному контексті, найкращим рішенням є реалізація випадкових власних зусиль у чистому котліні для спільного використання одного і того ж генератора випадкових чисел між платформами. Це простіше для розробників і тестування.
Щоб відповісти на цю проблему в особистому проекті, я реалізую чистий лінійний конгрурентний генератор Котліна . LCG - алгоритм, яким користуються java.util.Random
. Перейдіть за цим посиланням, якщо бажаєте ним скористатися:
https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4
Моя мета nextInt(range: IntRange)
для вас;).
Подбайте про моє призначення, LCG хороший для більшості випадків використання (моделювання, ігри тощо), але не підходить для використання криптографічно через передбачуваність цього методу.
Якщо числа, які ви хочете вибрати, не є послідовними, ви можете використовувати random()
.
Використання:
val list = listOf(3, 1, 4, 5)
val number = list.random()
Повертає одне з номерів, що знаходяться у списку.
Використовуючи функцію верхнього рівня, ви можете домогтися того самого синтаксису виклику, що і в Ruby (як хочете):
fun rand(s: Int, e: Int) = Random.nextInt(s, e + 1)
Використання:
rand(1, 3) // returns either 1, 2 or 3
По-перше, вам потрібен RNG. На даний момент у Котліні вам потрібно використовувати конкретні платформи (у них немає вбудованого Kotlin). Для віртуальної машини Java це java.util.Random
. Вам потрібно буде створити його примірник, а потім зателефонувати random.nextInt(n)
.
Для отримання випадкового Int числа в Котліні використовуйте наступний метод :
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
Сподіваюся, це допомагає.
Ви можете створити функцію розширення:
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()
}
Значення круглого поплавця:
fun Float.round(decimals: Int = DIGITS): Float {
var multiplier = 1.0f
repeat(decimals) { multiplier *= 10 }
return round(this * multiplier) / multiplier
}
Використання методу:
(0.0f .. 1.0f).step(.1f).forEach { System.out.println("value: $it") }
Вихід:
значення: 0,0 значення: 0,1 значення: 0,2 значення: 0,3 значення: 0,4 значення: 0,5 значення: 0,6 значення: 0,7 значення: 0,8 значення: 0,9 значення: 1,0
Повний вихідний код. Може контролювати, чи дозволені копії.
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("")
}
}
}
Щоразу, коли виникає ситуація, коли ви хочете генерувати ключ або mac-адресу, яка є шістнадцятковим числом, має цифри на основі попиту користувача, а також, використовуючи android та kotlin, то мій нижче код допоможе вам:
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()
}
бути супер пупер))
fun rnd_int(min: Int, max: Int): Int {
var max = max
max -= min
return (Math.random() * ++max).toInt() + min
}
java.util.Random
?