我怎样才能在Kotlin中得到一个随机数字?
一个generics的方法,可以返回一个随机整数之间的2个参数,如ruby与rand(0..n)
。
任何建议?
生成from
(包括) to
(独占)之间的随机整数
import java.util.Random val random = Random() fun rand(from: Int, to: Int) : Int { return random.nextInt(to - from) + from }
我建议在ClosedRange上使用下面的扩展函数:
fun ClosedRange.random() = Random().nextInt(endInclusive - start) + start
像这样使用它:
// will return an `Int` between 0 and 9 (incl.) (0..10).random()
如果您正在使用JDK> = 1.7,请使用ThreadLocalRandom.current()
而不是Random()
。
另请参阅此答案的变化。
你可以创建一个类似于java.util.Random.nextInt(int)
的扩展函数 ,但是它的绑定需要一个IntRange
而不是Int
。
fun Random.nextInt(range: IntRange): Int { return range.start + nextInt(range.last - range.start) }
你现在可以在任何实例中使用它:
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
建立@ s1m0nw1优秀的答案我做了以下更改。
- (0..n)意味着包含在Kotlin中
- (0至n)意味着在Kotlin独家
- 为Random实例使用单例对象(可选)
码:
private object RandomRangeSingleton : Random() fun ClosedRange.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()) } ) }
首先,你需要一个RNG。 在Kotlin中,您目前需要使用平台特定的平台(没有内置Kotlin)。 对于JVM,它是java.util.Random
。 你需要创建一个实例,然后调用random.nextInt(n)
。
没有这样的标准方法,但是使用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) = random(pair.first, pair.second) fun main(args: Array) { 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]
使用顶级函数,您可以实现与Ruby中完全相同的调用语法(如您所愿):
fun rand(s: Int, e: Int) = Random().nextInt(e + 1 - s) + s
用法:
rand(1, 3) // returns either 1, 2 or 3
上面我的答案可能的变化
a)如果您希望0..10.random()
也包含值10
,则需要进行以下更改:
fun ClosedRange.random() = Random().nextInt(endInclusive + 1 - start) + start
b)为了得到随机的Char
,你可以定义如下函数:
fun ClosedRange.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.7,请使用ThreadLocalRandom.current()
而不是Random()
。
如果您想选择的号码不是连续的,您可以在List上定义自己的扩展function:
fun List<*>.randomElement() = if (this.isEmpty()) null else this[Random().nextInt(this.size)]
用法:
val list = listOf(3, 1, 4, 5) val number = list.randomElement()
返回列表中的一个数字。
Kotlin标准库不提供随机数生成器API。 如果你不是在一个多平台的项目,最好使用平台API (所有其他答案的问题谈论这个解决方案) 。
但是,如果您处于多平台环境中,最好的解决方案是在纯kotlin中自行实现,以便在平台之间共享相同的随机数字生成器。 开发和测试更简单。
为了在我的个人项目中回答这个问题,我实现了一个纯Kotlin 线性同余发生器 。 LCG是java.util.Random
使用的算法。 按照这个链接,如果你想使用它: https : //gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4
我的实现目的nextInt(range: IntRange)
为你;)。
注意我的目的,LCG对大多数用例(模拟,游戏等)都有好处,但是由于这种方法的可预测性,不适合密码使用。