Làm thế nào tôi có thể nhận được một số ngẫu nhiên trong Kotlin?


151

Một phương thức chung có thể trả về một số nguyên ngẫu nhiên giữa 2 tham số như ruby ​​thực hiện với rand(0..n).

Bất kì lời đề nghị nào?

Câu trả lời:


373

Đề xuất của tôi sẽ là một chức năng mở rộng trên IntRange để tạo các randoms như thế này:(0..10).random()

TL; DR Kotlin> = 1.3, một Ngẫu nhiên cho tất cả các nền tảng

Kể từ 1.3, Kotlin đi kèm với trình tạo ngẫu nhiên đa nền tảng của riêng mình. Nó được mô tả trong KEEP này . Phần mở rộng được mô tả dưới đây hiện là một phần của thư viện tiêu chuẩn Kotlin , chỉ cần sử dụng nó như thế này:

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

Kotlin <1.3

Trước 1.3, trên JVM, chúng tôi sử dụng Randomhoặc ngay cả ThreadLocalRandomkhi chúng tôi sử dụng JDK> 1.6.

fun IntRange.random() = 
       Random().nextInt((endInclusive + 1) - start) + start

Được sử dụng như thế này:

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()

Nếu bạn chỉ muốn hàm trả về 1, 2, ..., 9( 10không bao gồm), hãy sử dụng một phạm vi được xây dựng với until:

(0 until 10).random()

Nếu bạn đang làm việc với JDK> 1.6, hãy sử dụng ThreadLocalRandom.current()thay vì Random().

KotlinJs và các biến thể khác

Đối với kotlinjs và các trường hợp sử dụng khác không cho phép sử dụng java.util.Random, hãy xem phương án này .

Ngoài ra, xem câu trả lời này cho các biến thể của đề nghị của tôi. Nó cũng bao gồm một hàm mở rộng cho Chars ngẫu nhiên .


Tôi giả sử điều này cũng sử dụng Java java.util.Random?
Simon Forsberg

@SimonForsberg Thật vậy. Tôi đã thêm một câu trả lời không sử dụng nó: stackoverflow.com/a/49507413/8073652
s1m0nw1

Ngoài ra còn có một đề xuất ở đây để thêm Trình tạo số giả ngẫu nhiên an toàn (CSPRNG) ở đây: github.com/Kotlin/KEEP/issues/184
Jonathan Leitschuh

41

Tạo một số nguyên ngẫu nhiên giữa from(bao gồm) và to(độc quyền)

import java.util.Random

val random = Random()

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

1
Nếu bạn muốn có một vài Ints ngẫu nhiên trong phạm vi, bạn có thể sử dụng Random # int (kích thước, từ, đến) thay vào đó trong java-8 .
holi-java

3
Giải pháp này không hoạt động trên Javascript / Native Kotlin. Có lẽ thật tuyệt khi tạo ra một phương pháp chung chung hơn để làm điều này. :)
Valentin Michalak

@ValentinMichalak bạn có thể thử cái này: stackoverflow.com/a/49507413/8073652
s1m0nw1

31

Kể từ kotlin 1.2, bạn có thể viết:

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

Chỉ cần lưu ý rằng đó là O (n) lớn, nhưng đối với một danh sách nhỏ (đặc biệt là các giá trị duy nhất) thì không sao: D


cái này hữu ích cho kotlin -igen
user3471194

11

Bạn có thể tạo một chức năng mở rộng tương tự java.util.Random.nextInt(int)nhưng một chức năngIntRange thay thế cho một Intràng buộc của nó:

fun Random.nextInt(range: IntRange): Int {
    return range.start + nextInt(range.last - range.start)
}

Bây giờ bạn có thể sử dụng điều này với bất kỳ Randomtrường hợp nào :

val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, or 8

Nếu bạn không muốn phải quản lý Randomcá thể của riêng mình thì bạn có thể xác định phương thức tiện lợi bằng cách sử dụng, ví dụ ThreadLocalRandom.current():

fun rand(range: IntRange): Int {
    return ThreadLocalRandom.current().nextInt(range)
}

Bây giờ bạn có thể nhận được một số nguyên ngẫu nhiên như trong Ruby mà không cần phải tự khai báo một Randomthể hiện:

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

10

Biến thể có thể cho câu trả lời khác của tôi cho ký tự ngẫu nhiên

Để có được Chars ngẫu nhiên , bạn có thể xác định hàm mở rộng như thế này

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

Nếu bạn đang làm việc với JDK> 1.6, hãy sử dụng ThreadLocalRandom.current() thay vì Random().

Đối với kotlinjs và các trường hợp sử dụng khác không cho phép sử dụng java.util.Random, câu trả lời này sẽ có ích.

Kotlin> = 1.3 hỗ trợ đa nền tảng cho Ngẫu nhiên

Kể từ 1.3, Kotlin đi kèm với trình tạo ngẫu nhiên đa nền tảng của riêng nó. Nó được mô tả trong KEEP này . Bây giờ bạn có thể trực tiếp sử dụng tiện ích mở rộng như một phần của thư viện chuẩn Kotlin mà không cần xác định nó:

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

7

Xây dựng câu trả lời xuất sắc @ s1m0nw1 Tôi đã thực hiện các thay đổi sau.

  1. (0..n) ngụ ý bao gồm trong Kotlin
  2. (0 cho đến n) ngụ ý độc quyền trong Kotlin
  3. Sử dụng một đối tượng singleton cho ví dụ Ngẫu nhiên (tùy chọn)

Mã số:

private object RandomRangeSingleton : Random()

fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start

Trường hợp thử nghiệm:

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

Các ví dụ ngẫu nhiên trong phạm vi [1, 10]

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

hoặc sử dụng Java Random

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

1
Câu trả lời đầu tiên của bạn tôi thích nhất. Đây là một lớp lót hoàn hảo không yêu cầu viết bất kỳ chức năng mở rộng nào
Alex Semeniuk 24/07/18

4

Kotlin> = 1.3, hỗ trợ đa nền tảng cho Ngẫu nhiên

Kể từ 1.3, thư viện tiêu chuẩn cung cấp hỗ trợ đa nền tảng cho các randoms, hãy xem câu trả lời này .

Kotlin <1.3 trên JavaScript

Nếu bạn đang làm việc với JavaScript Kotlin và không có quyền truy cập java.util.Random, những điều sau đây sẽ hoạt động:

fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()

Được sử dụng như thế này:

// will return an `Int` between 0 and 10 (incl.)
(0..10).random()

4

Một cách khác để thực hiện câu trả lời của s1m0nw1 là truy cập nó thông qua một biến. Không phải là nó hiệu quả hơn nhưng nó giúp bạn không phải gõ ().

val ClosedRange<Int>.random: Int
    get() = Random().nextInt((endInclusive + 1) - start) +  start 

Và bây giờ nó có thể được truy cập như vậy

(1..10).random

2

Không có phương pháp tiêu chuẩn nào thực hiện điều này nhưng bạn có thể dễ dàng tạo riêng của mình bằng cách sử dụng Math.random()hoặc lớp java.util.Random. Dưới đây là một ví dụ sử dụng Math.random()phương thức:

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

Đây là một đầu ra mẫu:

[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]

2

Liblin tiêu chuẩn lib không cung cấp API Trình tạo số ngẫu nhiên. Nếu bạn không tham gia dự án đa nền tảng, tốt hơn là sử dụng api nền tảng (tất cả các câu trả lời khác của câu hỏi đều nói về giải pháp này) .

Nhưng nếu bạn đang ở trong một bối cảnh đa nền tảng, giải pháp tốt nhất là tự mình thực hiện ngẫu nhiên trong kotlin thuần túy để chia sẻ cùng một trình tạo số ngẫu nhiên giữa các nền tảng. Nó đơn giản hơn cho dev và thử nghiệm.

Để trả lời cho vấn đề này trong dự án cá nhân của tôi, tôi triển khai một Trình tạo cộng tuyến tuyến tính thuần túy của Kotlin . LCG là thuật toán được sử dụng bởi java.util.Random. Theo liên kết này nếu bạn muốn sử dụng nó: https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4

Mục đích thực hiện của tôi nextInt(range: IntRange)cho bạn;).

Hãy quan tâm đến mục đích của tôi, LCG tốt cho hầu hết các trường hợp sử dụng (mô phỏng, trò chơi, v.v ...) nhưng không phù hợp để sử dụng mật mã vì khả năng dự đoán của phương pháp này.


Tôi thà dựa vào mã cụ thể của nền tảng hơn là tạo ra thuật toán ngẫu nhiên của riêng tôi. Điều này nhắc nhở tôi một chút về mã cho java.util.Random, nhưng nó không hoàn toàn khớp.
Simon Forsberg

2

Trong Kotlin 1.3 bạn có thể làm như thế

val number = Random.nextInt(limit)

2

Nếu các số bạn muốn chọn không liên tiếp, bạn có thể sử dụng random().

Sử dụng:

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

Trả về một trong những số có trong danh sách.


2

Không cần phải sử dụng các chức năng mở rộng tùy chỉnh nữa. IntRange hiệnrandom()chức năng mở rộng.

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

2

Sử dụng hàm cấp cao nhất, bạn có thể đạt được chính xác cú pháp cuộc gọi giống như trong Ruby (như bạn muốn):

fun rand(s: Int, e: Int) = Random.nextInt(s, e + 1)

Sử dụng:

rand(1, 3) // returns either 1, 2 or 3

1

Đầu tiên, bạn cần có RNG. Trong Kotlin hiện tại bạn cần sử dụng các nền tảng cụ thể (không có Kotlin được tích hợp trong một). Đối với JVM, nó java.util.Random. Bạn sẽ cần tạo một thể hiện của nó và sau đó gọi random.nextInt(n).


1

Để có được số Int ngẫu nhiên trong Kotlin, hãy sử dụng phương pháp sau :

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

Hi vọng điêu nay co ich.


0

Bạn có thể tạo một chức năng mở rộng:

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

Giá trị phao tròn:

fun Float.round(decimals: Int = DIGITS): Float {
    var multiplier = 1.0f
    repeat(decimals) { multiplier *= 10 }
    return round(this * multiplier) / multiplier
}

Cách sử dụng:

(0.0f .. 1.0f).step(.1f).forEach { System.out.println("value: $it") }

Đầu ra:

giá trị: 0,0 giá trị: 0,1 giá trị: 0,2 giá trị: 0,3 giá trị: 0,4 giá trị: 0,5 giá trị: 0,6 giá trị: 0,7 giá trị: 0,8 giá trị: 0,9 giá trị: 1,0


0

Mã nguồn đầy đủ. Có thể kiểm soát xem các bản sao được cho phép.

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

Bất cứ khi nào có tình huống bạn muốn tạo địa chỉ khóa hoặc mac là số thập lục phân có các chữ số dựa trên nhu cầu của người dùng và việc sử dụng android và kotlin cũng vậy, thì mã dưới đây của tôi sẽ giúp bạn:

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

trở thành siêu lừa đảo))

 fun rnd_int(min: Int, max: Int): Int {
        var max = max
        max -= min
        return (Math.random() * ++max).toInt() + min
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.