我如何在Kotlin中获得一个随机数?

问题描述 投票:95回答:19

一个泛型方法,可以返回2个参数之间的随机整数,如ruby与rand(0..n)

有什么建议吗?

random kotlin jvm
19个回答
272
投票

我的建议是extension上的IntRange函数来创建这样的randoms:(0..10).random()

TL; DR Kotlin> = 1.3,所有平台都有一个随机数

从1.3开始,Kotlin自带多平台随机发生器。它在这个KEEP中描述。下面描述的扩展现在是part of the Kotlin standard library,只需使用它:

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

Kotlin < 1.3

在1.3之前,如果JDK> 1.6,我们在JVM上使用Random甚至ThreadLocalRandom

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和其他变种

对于kotlinjs和其他不允许使用java.util.Random的用例,请参阅this alternative

此外,请参阅此answer我的建议的变化。它还包括随机Chars的扩展功能。


2
投票

没有标准方法可以做到这一点,但您可以使用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]

2
投票

如果您要选择的数字不是连续的,则可以使用random()

用法:

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

返回列表中的一个数字。


2
投票

使用顶级函数,您可以实现与Ruby中完全相同的调用语法(如您所愿):

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

用法:

rand(1, 3) // returns either 1, 2 or 3

1
投票

首先,你需要一个RNG。在Kotlin中,您目前需要使用平台特定的(没有内置的Kotlin)。对于JVM来说,它是java.util.Random。您需要创建它的实例,然后调用random.nextInt(n)


1
投票

Kotlin标准库不提供随机数生成器API。如果您不在多平台项目中,最好使用平台api(问题的所有其他答案都谈论此解决方案)。

但是如果你处于多平台环境中,最好的解决方案是在纯kotlin中自己实现随机,以便在平台之间共享相同的随机数生成器。开发和测试更简单。

为了在我的个人项目中回答这个问题,我实现了一个纯粹的Kotlin Linear Congruential Generator。 LCG是java.util.Random使用的算法。如果您想使用它,请点击此链接:https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

我的实施目的nextInt(range: IntRange)为你;)。

关注我的目的,LCG适用于大多数用例(模拟,游戏等......),但由于此方法的可预测性,因此不适合加密使用。


1
投票

在Kotlin 1.3中你可以这样做

val number = Random.nextInt(limit)

1
投票

无需再使用自定义扩展功能。 IntRange现在有一个开箱即用的random()扩展功能。

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

0
投票

要在Kotlin中获取随机的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

希望这可以帮助。


0
投票

您可以创建扩展功能:

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

Round Float值:

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


-1
投票

超级骗子))

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

39
投票

生成from(包括)和to(不包括)之间的随机整数

import java.util.Random

val random = Random()

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

27
投票

从kotlin 1.2开始,你可以写:

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

请注意它是大O(n),但对于一个小列表(尤其是唯一值),它没关系:D


10
投票

您可以创建一个类似于extension functionjava.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

8
投票

我的other answer随机字符的可能变化

为了获得随机Chars,您可以定义这样的扩展函数

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() instead of Random()

对于kotlinjs和其他不允许使用java.util.Random的用例,this answer会有所帮助。

Kotlin> = 1.3多平台支持Random

从1.3开始,Kotlin自带多平台随机发生器。它在这个KEEP中描述。您现在可以直接将扩展名作为Kotlin标准库的一部分使用,而无需定义它:

('a'..'b').random()

7
投票

建立@s1m0nw1优秀的答案我做了以下的改变。

  1. (0..n)意味着在Kotlin中包容
  2. (0到n)意味着在Kotlin独家
  3. 对Random实例使用单例对象(可选)

码:

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

6
投票

在[1,10]范围内随机的例子

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

或利用Java Random

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

4
投票

Kotlin> = 1.3,对Random的多平台支持

从1.3开始,标准库为random提供了多平台支持,请参阅this的答案。

JavaScript上的Kotlin <1.3

如果您正在使用Kotlin JavaScript并且无法访问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()

4
投票

实现s1m0nw1的答案的另一种方法是通过变量访问它。并不是说它更有效,但它可以让你免于输入()。

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

现在它可以这样访问

(1..10).random
© www.soinside.com 2019 - 2024. All rights reserved.