ฉันจะรับหมายเลขสุ่มใน Kotlin ได้อย่างไร


151

วิธีการทั่วไปที่สามารถกลับจำนวนเต็มสุ่มระหว่าง 2 rand(0..n)พารามิเตอร์เช่นทับทิมจะมี

ข้อเสนอแนะใด ๆ

คำตอบ:


375

ข้อเสนอแนะของฉันจะเป็นฟังก์ชันส่วนขยายในIntRangeเพื่อสร้าง randoms ดังนี้:(0..10).random()

TL; DR Kotlin> = 1.3 หนึ่งการสุ่มสำหรับทุกแพลตฟอร์ม

ในฐานะของ 1.3, Kotlin มาพร้อมกับเครื่องกำเนิดไฟฟ้าแบบสุ่มหลายแพลตฟอร์มของตัวเอง อธิบายไว้ในKEEPนี้ ส่วนขยายที่อธิบายด้านล่างนี้เป็นส่วนหนึ่งของไลบรารีมาตรฐาน Kotlinเพียงใช้อย่างนี้:

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

Kotlin <1.3

ก่อนหน้า 1.3 บน JVM ที่เราใช้Randomหรือแม้ว่าThreadLocalRandomเราจะใช้ JDK> 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()

KotlinJs และรูปแบบอื่น ๆ

สำหรับ kotlinjs และกรณีการใช้งานอื่น ๆ ที่ไม่อนุญาตให้ใช้java.util.Randomดูที่ตัวเลือกนี้

ดูคำตอบนี้สำหรับคำแนะนำของฉันที่หลากหลาย นอกจากนี้ยังมีฟังก์ชั่นเสริมสำหรับการสุ่มChars


ฉันคิดว่านี่ยังใช้ของ Java java.util.Random?
Simon Forsberg

@SimonForsberg แน่นอน ฉันได้เพิ่มคำตอบอื่นที่ไม่ได้ใช้แล้ว: stackoverflow.com/a/49507413/8073652
s1m0nw1

นอกจากนี้ยังมีข้อเสนอที่นี่เพื่อเพิ่ม Cryptographically Secure Pseudo-Random Number Generator (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
หากคุณต้องการที่จะได้รับคู่ของ ranged สุ่มInts คุณสามารถใช้สุ่ม # int (ขนาดจากไป)แทนในJava-8
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) แต่สำหรับรายการเล็ก ๆ


อันนี้มีประโยชน์สำหรับ 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)
}

ตอนนี้คุณสามารถรับจำนวนเต็มแบบสุ่มได้ตามที่คุณต้องการใน Ruby โดยไม่ต้องประกาศRandomตัวเองก่อน:

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 มาพร้อมกับตัวสร้าง Random Multiplatform อธิบายไว้ในKEEPนี้ ตอนนี้คุณสามารถใช้ส่วนขยายเป็นส่วนหนึ่งของไลบรารีมาตรฐาน Kotlin ได้โดยตรงโดยไม่ต้องกำหนด:

('a'..'b').random()

7

การสร้าง@ @ s1m0nw1คำตอบที่ดีฉันทำการเปลี่ยนแปลงดังต่อไปนี้

  1. (0..n) หมายถึงรวมอยู่ใน Kotlin
  2. (0 ถึง n) หมายถึงพิเศษใน Kotlin
  3. ใช้วัตถุ Singleton สำหรับอินสแตนซ์ 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, ห้องสมุดมาตรฐานให้การสนับสนุนหลายแพลตฟอร์มสำหรับ randoms ดูนี้คำตอบ

Kotlin <1.3 บน JavaScript

หากคุณทำงานกับ 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


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

lib มาตรฐานของ Kotlin ไม่ได้ให้ Random Number Generator API หากคุณไม่ได้อยู่ในโครงการที่มีหลายแพลตฟอร์มคุณควรใช้แพลตฟอร์ม API (ทุกคำตอบอื่น ๆ ของคำถามพูดคุยเกี่ยวกับโซลูชันนี้)คำตอบของการพูดคุยเกี่ยวกับการแก้ปัญหานี้)

แต่ถ้าคุณอยู่ในบริบทที่หลากหลายแพลตฟอร์มทางออกที่ดีที่สุดคือการใช้การสุ่มด้วยตัวเองใน kotlin บริสุทธิ์เพื่อแบ่งปันเครื่องกำเนิดตัวเลขสุ่มแบบเดียวกันระหว่างแพลตฟอร์มง่ายกว่าสำหรับการพัฒนาและทดสอบ

หากต้องการคำตอบให้กับปัญหานี้ในโครงการส่วนบุคคลของฉันฉันใช้บริสุทธิ์ Kotlin เชิงเส้น congruential ปั่นไฟ 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

ไม่จำเป็นต้องใช้ฟังก์ชั่นส่วนขยายที่กำหนดเองอีกต่อไป IntRangeมีrandom()ฟังก์ชั่นส่วนขยายนอกกรอบทันที

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

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

ในการรับหมายเลข Int แบบสุ่มใน Kotlin ให้ใช้วิธีการต่อไปนี้ :

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

เมื่อใดก็ตามที่มีสถานการณ์ที่คุณต้องการสร้างคีย์หรือที่อยู่ 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.