如何在 Kotlin 中获取随机数?
Posted
技术标签:
【中文标题】如何在 Kotlin 中获取随机数?【英文标题】:How can I get a random number in Kotlin? 【发布时间】:2018-01-22 21:54:00 【问题描述】:一种可以返回两个参数之间的随机整数的通用方法,就像 ruby 对 rand(0..n)
所做的那样。
有什么建议吗?
【问题讨论】:
【参考方案1】:首先,您需要一个 RNG。在 Kotlin 中,您目前需要使用特定于平台的那些(没有内置的 Kotlin)。对于 JVM,它是 java.util.Random
。您需要创建它的一个实例,然后调用random.nextInt(n)
。
【讨论】:
【参考方案2】:在from
(含)和to
(不含)之间生成一个随机整数
import java.util.Random
val random = Random()
fun rand(from: Int, to: Int) : Int
return random.nextInt(to - from) + from
【讨论】:
如果你想得到几个远程随机Int
s,你可以在java-8中使用Random#int(size,from,to)。
此解决方案不适用于 javascript / Native Kotlin。也许制作一个更通用的方法来做到这一点可能很酷。 :)
@ValentinMichalak 你可以试试这个:***.com/a/49507413/8073652【参考方案3】:
没有执行此操作的标准方法,但您可以使用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]
【讨论】:
【参考方案4】:我的建议是在IntRange 上使用extension 函数来创建这样的随机数:(0..10).random()
TL;DR Kotlin >= 1.3,所有平台随机一个
从 1.3 开始,Kotlin 自带了自己的多平台随机生成器。这在KEEP 中有描述。下面描述的扩展现在是part of the Kotlin standard library,只需像这样使用它:
val rnds = (0..10).random() // generated random from 0 to 10 included
科特林
在 1.3 之前,在 JVM 上我们使用 Random
,如果我们在 JDK > 1.6 上,甚至使用 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 了解我的建议的变体。它还包括随机Char
s 的扩展功能。
【讨论】:
我假设这也使用了 Java 的java.util.Random
?
@SimonForsberg 确实如此。我添加了另一个没有使用它的答案:***.com/a/49507413/8073652
这里还有一个建议,在这里添加一个加密安全伪随机数生成器 (CSPRNG):github.com/Kotlin/KEEP/issues/184
val rnds = (0..10).random()
实际上生成 0 到 10,包括 10 和 0。 pl.kotl.in/1o8LyD1Dc
虽然每次通话都返回相同的号码,但它可以工作【参考方案5】:
您可以创建一个类似于java.util.Random.nextInt(int)
的extension function,但它的边界采用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, 8, or 9
如果您不想管理自己的 Random
实例,则可以使用例如 ThreadLocalRandom.current()
定义一个方便的方法:
fun rand(range: IntRange): Int
return ThreadLocalRandom.current().nextInt(range)
现在您可以像在 Ruby 中一样获得一个随机整数,而无需自己先声明一个 Random
实例:
rand(5..9) // returns 5, 6, 7, 8, or 9
【讨论】:
【参考方案6】:基于@s1m0nw1 出色的答案,我做了以下更改。
-
(0..n) 在 Kotlin 中表示包容
(0 到 n)在 Kotlin 中表示独占
为 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())
)
【讨论】:
【参考方案7】:我的other answer 随机字符的可能变化
为了得到随机的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
的用例,this answer 会有所帮助。
Kotlin >= 1.3 对 Random 的多平台支持
从 1.3 开始,Kotlin 自带了自己的多平台随机生成器。在KEEP 中有描述。您现在可以直接将扩展用作 Kotlin 标准库的一部分,而无需定义它:
('a'..'b').random()
【讨论】:
【参考方案8】:使用***函数,您可以实现与 Ruby 中完全相同的调用语法(如您所愿):
fun rand(s: Int, e: Int) = Random.nextInt(s, e + 1)
用法:
rand(1, 3) // returns either 1, 2 or 3
【讨论】:
【参考方案9】:如果要选择的数字不连续,可以使用random()
。
用法:
val list = listOf(3, 1, 4, 5)
val number = list.random()
返回列表中的数字之一。
【讨论】:
【参考方案10】:Kotlin 标准库不提供随机数生成器 API。如果您不在多平台项目中,最好使用平台 api(所有其他问题的答案都在谈论这个解决方案)。
但是如果你在多平台环境中,最好的解决方案是在纯 kotlin 中自己实现 random,以便在平台之间共享相同的随机数生成器。对于开发和测试来说更简单。
为了在我的个人项目中解决这个问题,我实现了一个纯 Kotlin Linear Congruential Generator。 LCG 是java.util.Random
使用的算法。如果您想使用它,请点击此链接:
https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4
我的实现目的nextInt(range: IntRange)
给你;)。
注意我的目的,LCG 适用于大多数用例(模拟、游戏等),但由于这种方法的可预测性,它不适合加密使用。
【讨论】:
我宁愿依赖特定于平台的代码,也不愿自己制作随机算法。这让我想起了一些关于 java.util.Random 的代码,但它并不完全匹配。【参考方案11】:从 kotlin 1.2 开始,您可以这样写:
(1..3).shuffled().last()
请注意它的 O(n) 很大,但对于一个小列表(尤其是唯一值)来说没关系:D
【讨论】:
这个对kotlin-native很有用【参考方案12】:Kotlin >= 1.3,对 Random 的多平台支持
从 1.3 开始,标准库为随机数提供了多平台支持,请参阅 this 答案。
Kotlin
如果您使用 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()
【讨论】:
【参考方案13】:[1, 10] 范围内的随机示例
val random1 = (0..10).shuffled().last()
或使用 Java Random
val random2 = Random().nextInt(10) + 1
【讨论】:
你的第一个回答我最喜欢。这是一个完美的单行代码,不需要编写任何扩展函数 @AlexSemeniuk 请不要。shuffled()
将返回一个列表。想象一下如果你通过(0..Integer.MAX_VALUE)
会发生什么
@deviant 好点。只是我有一个用例,我需要从集合中获取随机元素。【参考方案14】:
实现 s1m0nw1 答案的另一种方法是通过变量访问它。并不是说它更有效,而是让您不必键入 ()。
val ClosedRange<Int>.random: Int
get() = Random().nextInt((endInclusive + 1) - start) + start
现在可以这样访问了
(1..10).random
【讨论】:
【参考方案15】:在 Kotlin SDK >=1.3 中,您可以这样做
import kotlin.random.Random
val number = Random.nextInt(limit)
【讨论】:
【参考方案16】:成为超级骗子))
fun rnd_int(min: Int, max: Int): Int
var max = max
max -= min
return (Math.random() * ++max).toInt() + min
【讨论】:
【参考方案17】:不再需要使用自定义扩展功能。 IntRange 现在有一个开箱即用的 random()
扩展功能。
val randomNumber = (0..10).random()
【讨论】:
【参考方案18】:要在 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
希望这会有所帮助。
【讨论】:
【参考方案19】:你可以创建一个扩展函数:
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
【讨论】:
【参考方案20】:完整的源代码。可以控制是否允许重复。
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("")
【讨论】:
【参考方案21】:当您想要生成密钥或 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()
【讨论】:
【参考方案22】:下面的 Kotlin 对我来说效果很好:
(fromNumber.rangeTo(toNumber)).random()
数字范围以变量fromNumber
开始,以变量toNumber
结束。 fromNumber
和 toNumber
也将包含在由此生成的随机数中。
【讨论】:
以上是关于如何在 Kotlin 中获取随机数?的主要内容,如果未能解决你的问题,请参考以下文章