2017-08-15 18 views

Trả lời

23

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 nhận được một vài thay đổi ngẫu nhiên 'Int' s, bạn có thể sử dụng [Random # int (size, from, to)] (http://docs.oracle.com/javase/8/docs/api/java /util/Random.html#ints-long-int-int-) thay vào đó trong [tag: java-8]. –

+2

Giải pháp này không hoạt động trên Javascript/Native Kotlin. Có lẽ nó có thể được mát mẻ để làm cho một phương pháp chung chung hơn để làm điều này. :) –

1

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

1

Không có phương pháp tiêu chuẩn mà thực hiện điều này nhưng bạn có thể dễ dàng tạo của riêng bạn 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 pháp:

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 sản lượng mẫu:

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

tôi đề nghị sử dụng extension chức năng sau trên ClosedRange:

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

Và sử dụng nó như thế này:

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

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

Ngoài ra, hãy xem điều này answer cho các biến thể của đề xuất của tôi. Nó cũng bao gồm một chức năng mở rộng cho ngẫu nhiên Char s.

8

Bạn có thể tạo một extension function tương tự như java.util.Random.nextInt(int) nhưng một trong đó có một IntRange thay vì một Int cho rà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 với bất kỳ Random dụ:

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

Nếu bạn không muốn quản lý trường hợp Random 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ư bạn làm trong Ruby mà không cần phải khai báo một ví dụ Random mình:

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

Building tắt của @s1m0nw1 câu trả lời tuyệt vời tôi đã thực hiện những thay đổi sau.

  1. (0 ..n) có nghĩa bao gồm trong Kotlin
  2. (0 đến n) ngụ ý độc quyền tại Kotlin
  3. Sử dụng một đối tượng singleton cho các trường hợp ngẫu nhiên (không bắt buộc)

Code:

private object RandomRangeSingleton : Random() 

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

Test Case:

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

Các biến thể có thể có cho câu trả lời của tôi above

a) Nếu bạn muốn 0..10.random() tới cũng bao gồm giá trị 10, sự thay đổi sau đây là cần thiết:

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

b) Để có được ngẫu nhiên Char s, bạn có thể xác định một chức năng 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.7, hãy sử dụng ThreadLocalRandom.current() thay vì Random().

1

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

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

Cách sử dụng:

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

Nếu số bạn muốn lựa chọn không liên tiếp, bạn có thể xác định chức năng mở rộng của riêng bạn trên Danh sách:

fun List<*>.randomElement() 
    = if (this.isEmpty()) null else this[Random().nextInt(this.size)] 

Cách sử dụng:

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

Trả về một trong các số nằm trong danh sách.

1

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

Nhưng nếu bạn đang ở trong 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 để 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 Kotlin Linear Congruential Generator tinh khiết. LCG là thuật toán được sử dụng bởi java.util.Random. Nhấp vào liên kết này nếu bạn muốn sử dụng liên kết này: 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ã hóa do khả năng dự đoán của phương pháp này.

1

Tính đến Kotlin 1.2, bạn có thể viết:

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

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

Các vấn đề liên quan