Kotlinで乱数を取得するにはどうすればよいですか?


151

rubyのように2つのパラメーターの間にランダムな整数を返すことができるジェネリックメソッドrand(0..n)

なにか提案を?

回答:


373

私の提案は、次のようなランダムを作成するためのIntRangeの拡張関数です。(0..10).random()

TL; DR Kotlin> = 1.3、すべてのプラットフォームで1つのランダム

1.3以降、Kotlinには独自のマルチプラットフォームランダムジェネレーターが付属しています。このKEEPで説明されています。以下で説明する拡張機能は、Kotlin標準ライブラリの一部になりました。次のように使用してください。

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

コトリン<1.3

1.3より前のバージョンでは、JVMで、RandomまたはThreadLocalRandomJDK> 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, ..., 910含まれていない)場合は、次のように構成された範囲を使用しますuntil

(0 until 10).random()

JDK> 1.6で作業している場合は、のThreadLocalRandom.current()代わりにを使用してくださいRandom()

KotlinJsとその他のバリエーション

kotlinjsや、の使用を許可しないその他の使用例java.util.Randomについては、この代替方法をご覧ください。

また、私の提案のバリエーションについては、この回答を参照してください。また、ランダムCharsの拡張関数も含まれています。


これもJavaを使用しているとjava.util.Random思いますか?
Simon Forsberg

@SimonForsberg確かに。私はそれを使用しない別の回答を追加しました:stackoverflow.com/a/49507413/8073652
s1m0nw1

暗号で安全な疑似乱数ジェネレータ(CSPRNG)をここに追加する提案もここにあります:github.com/Kotlin/KEEP/issues/184
Jonathan Leitschuh

41

from(包括的)とto(排他的)の間のランダムな整数を生成します

import java.util.Random

val random = Random()

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

1
いくつかの範囲のランダムなを取得したい場合は、代わりにRandom#int(size、from、to)java-8でInt使用できます。
holi-java 2017

3
このソリューションは、Javascript / Native Kotlinでは機能しません。おそらく、これを行うためのより一般的な方法を作成するのがクールかもしれません。:)
Valentin Michalak

@ValentinMichalakこれを試すことができます:stackoverflow.com/a/49507413/8073652
s1m0nw1 2018年

31

kotlin 1.2以降、次のように記述できます。

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

大きなO(n)であることに注意してください。ただし、小さなリスト(特に一意の値)の場合は問題ありません:D


これは、kotlinネイティブに役立ちます
user3471194 '28 / 10/28

11

に似た拡張関数を作成できますが、その境界に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)
}

これで、最初にRandomインスタンスを自分で宣言しなくても、Rubyの場合と同じようにランダムな整数を取得できます。

rand(5..9) // returns 5, 6, 7, or 8

10

ランダムな文字に関する他の回答に対するバリエーションの可能性

ランダムな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この回答が役立ちます。

Kotlin> = 1.3ランダムのマルチプラットフォームサポート

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

5

[1、10]の範囲でランダムな例

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

またはJavaランダムを利用する

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

1
あなたの最初の答えは私が一番好きです。これは、拡張機能を記述する必要がない完璧なワンライナーです
Alex Semeniuk 2018

4

Kotlin> = 1.3、ランダムのマルチプラットフォームサポート

1.3以降、標準ライブラリはランダムに対してマルチプラットフォームサポートを提供しました。この回答を参照してください。

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

3

Kotlin 1.3では、次のようにすることができます

val number = Random.nextInt(limit)

2

これを行う標準メソッドはありませんが、Math.random()またはクラスを使用して簡単に独自のメソッドを作成できますjava.util.RandomMath.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

Kotlin標準ライブラリは、乱数ジェネレータAPIを提供していません。マルチプラットフォームプロジェクトに参加していない場合は、プラットフォームAPIを使用することをお勧めします(この質問に対する他のすべての回答は、このソリューションについて話しています)

ただし、マルチプラットフォームのコンテキストを使用している場合、最善の解決策は、純粋なkotlinに自分でランダムに実装して、プラットフォーム間で同じ乱数ジェネレータを共有することです。開発とテストの方が簡単です。

私の個人的なプロジェクトでこの問題に答えるために、私は純粋なKotlin 線形合同ジェネレーターを実装します。LCGはが使用するアルゴリズムjava.util.Randomです。使用する場合は、次のリンクにアクセスしてくださいhttps : //gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

私の実装目的 nextInt(range: IntRange)あなたのための ;)。

LCGはほとんどのユースケース(シミュレーション、ゲームなど)に適していますが、この方法は予測可能であるため、暗号での使用には適していません。


独自のランダムアルゴリズムを作成するよりも、プラットフォーム固有のコードに依存したいと思います。これは、java.util.Randomのコードについて少し思い出させますが、完全には一致しません。
Simon Forsberg、2018年



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でランダムな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()
}

ラウンドフロート値:

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


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

0

ユーザーの要求に基づいて数字を持つ16進数のキーまたは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()
} 

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.