Kotlin에서 난수를 어떻게 얻을 수 있습니까?


151

루비와 같이 두 매개 변수 사이의 임의의 정수를 반환 할 수있는 일반적인 방법은입니다 rand(0..n).

어떠한 제안?

답변:


373

내 제안은 IntRange 에서 다음과 같이 무작위 를 만드는 확장 함수입니다 .(0..10).random()

TL; DR Kotlin> = 1.3, 모든 플랫폼에서 하나의 랜덤

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, ..., 9( 10포함되지 않음) 다음으로 구성된 범위를 사용하십시오 until.

(0 until 10).random()

JDK> 1.6으로 작업하는 경우 ThreadLocalRandom.current()대신을 사용하십시오 Random().

KotlinJ 및 기타 변형

의 사용을 허용하지 않는 kotlinjs 및 기타 사용 사례 java.util.Random에 대해서는 이 대안을 참조하십시오 .

또한 내 제안의 변형에 대해서는이 답변 을 참조하십시오 . 또한 임의 Char의 확장 기능도 포함합니다 .


나는 이것이 Java를 사용한다고 가정한다 java.util.Random.
Simon Forsberg

@SimonForsberg 실제로. 나는 그것을 사용하지 않는 또 다른 대답을 추가했습니다 : stackoverflow.com/a/49507413/8073652
s1m0nw1

여기 안전한 암호화 의사 난수 생성기 (CSPRNG)를 추가하려면 여기를 제안도있다 : github.com/Kotlin/KEEP/issues/184
조나단 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
범위가 지정된 임의 Int의 랜덤을 얻으려면 java-8 대신 Random # int (size, from, to) 를 사용할 수 있습니다 .
holi-java

3
이 솔루션은 Javascript / Native Kotlin에서 작동하지 않습니다. 아마도이 작업을보다 일반적인 방법으로 만드는 것이 좋을 수도 있습니다. :)
Valentin Michalak

@ValentinMichalak 당신은 이것을 시도 할 수 있습니다 : stackoverflow.com/a/49507413/8073652
s1m0nw1

31

kotlin 1.2부터 다음과 같이 작성할 수 있습니다.

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

큰 O (n)이지만 작은 목록 (특히 고유 한 값)의 경우 괜찮습니다 .D


이것은 kotlin-native에 유용합니다
user3471194

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

임의의 문자에 대한 다른 대답 에 가능한 변형

랜덤을 얻기 위해 Char다음과 같은 확장 기능을 정의 할 수 있습니다

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 Random을 활용

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

1
첫 번째 대답은 내가 가장 좋아합니다. 확장 기능을 작성하지 않아도되는 완벽한 원 라이너입니다.
Alex Semeniuk

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.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

Kotlin 표준 라이브러리는 난수 생성기 API를 제공하지 않습니다. 다중 플랫폼 프로젝트를 사용하지 않는 경우 플랫폼 API를 사용하는 것이 좋습니다 (질문에 대한 다른 모든 답변은이 솔루션에 대해 설명합니다) .

그러나 다중 플랫폼 환경에있는 경우 최상의 솔루션은 플랫폼간에 동일한 난수 생성기를 공유하기 위해 순수 kotlin에서 직접 임의를 구현하는 것입니다. 개발 및 테스트가 더 간단합니다.

내 개인 프로젝트 에서이 문제에 답하기 위해 순수한 Kotlin Linear Congruential Generator를 구현합니다 . LCG는에서 사용하는 알고리즘 java.util.Random입니다. 사용하려면이 링크를 따르십시오 : https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

nextInt(range: IntRange)당신을위한 나의 구현 목적 ;).

LCG는 대부분의 사용 사례 (시뮬레이션, 게임 등)에 적합하지만이 방법의 예측 가능성으로 인해 암호 사용에는 적합하지 않습니다.


내 자신의 무작위 알고리즘을 만드는 것보다 플랫폼 특정 코드에 의존하고 싶습니다. 이것은 java.util.Random의 코드에 대해 조금 생각 나게하지만 완전히 일치하지는 않습니다.
Simon Forsberg

2

선택하려는 숫자가 연속적이지 않은 경우을 사용할 수 있습니다 random().

용법:

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

목록에있는 숫자 중 하나를 반환합니다.



2

최상위 함수를 사용하면 루비에서와 정확히 동일한 호출 구문을 얻을 수 있습니다 (원하는대로).

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 진수이고 안드로이드 및 kotlin을 사용하는 16 진수 키 또는 mac 주소를 생성하려는 상황이있을 때마다 아래 코드가 도움이됩니다.

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

-1

슈퍼 듀 퍼가 되려면))

 fun rnd_int(min: Int, max: Int): Int {
        var max = max
        max -= min
        return (Math.random() * ++max).toInt() + min
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.