如何在 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

【讨论】:

如果你想得到几个远程随机Ints,你可以在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 了解我的建议的变体。它还包括随机Chars 的扩展功能。

【讨论】:

我假设这也使用了 Java 的 java.util.Random? @SimonForsberg 确实如此。我添加了另一个没有使用它的答案:***.com/a/49507413/8073652 这里还有一个建议,在这里添加一个加密安全伪随机数生成器 (CSPRNG):github.com/Kotlin/KEEP/issues/184 val rnds = (0..10).random() 实际上生成 0 到 10,包括 100。 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 随机字符的可能变化

为了得到随机的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() 而不是 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 结束。 fromNumbertoNumber 也将包含在由此生成的随机数中。

【讨论】:

以上是关于如何在 Kotlin 中获取随机数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby 中获取随机数

如何在模板工具包中获取随机数?

如何在javascript中获取一位随机数? [复制]

如何在 OpenCL 中获取“随机”数

在SQL中怎么样获取随机数

如何使用汇编程序从英特尔处理器中获取随机数?