[Kotlin 小撇步 #8]四個產生隨機數字的方法

Andy Lu
6 min readJul 2, 2021
Photo by Nick Hillier on Unsplash

很多時候,我們希望能夠隨機產生數字。在 Java 中,我們可以使用 Math.random 回傳一個在 0~1 之間的一個 double 數。

那麼,在 Kotlin 除了使用 Math.random 之外,還有沒有其他 Kotlin 內建的方法可以產生隨機數呢?

在這篇文章中,我將介紹四種不同的方式產生隨機變數。

1. Random

第一個要介紹的,當然是要從Standard Lib 的 Random 類介紹起。

Random 包含了許多以 next 開頭命名的函式,例如:nextInt(), nextDouble(), nextLong(), nextFloat()

Random.nextInt()
//-2061105610
Random.nextDouble()
//0.4966379730773498
Random.nextLong()
//-4084004577217082135
Random.nextFloat()
//0.8338781

另外, nextInt(), nextDouble(), nextLong() 包含兩個重載的版本。

一個是從 0 ~指定的值;另一個則是數值的範圍是自訂的。

nextInt()

  1. nextInt(until: Int)
  2. nextInt(from: Int, until: Int)

nextDouble()

  1. nextDouble(until: Double)
  2. nextDouble(from: Double, until: Double)

nextLong()

  1. nextLong(until: Long)
  2. nextLong(from: Long, until: Long)

2. IntRange.random

假設你需要產生一個在一段 Int 範圍內的任意數,除了使用前面提到的 Random.nextInt(from: Double, until:Double),有另一個方法更符合 Kotlin 風格,那就是使用 IntRangerandom()函式。

假設我想要產生一個在 0~100 之間的數字。我可以先定義一個 IntRange,然後使用 random 函式,來取得一個在範圍內的數字。

(0 .. 100).random()
//50

3. Iterable.shuffled

在 Kotlin 的 Iterable 類中,我們可以利用 shuffled()函式將集合弄亂,然後隨機取一個值。實作 Iterable 的類,如 List, Set 或是前面介紹的 IntRange 都可以使用 shuffled 函式。

例如:

listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).shuffled()
//[7, 6, 1, 5, 0, 9, 2, 10, 8, 4, 3]

接下來我們只需要隨機取一個元素即可。在 Collections 中,我們可以使用 first() 函式取得集合的第一個元素、 last()函式取得最後一個元素或是直接使用 [ ] 取得特定位置的值。

listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).shuffled().first()
//7
listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).shuffled().last()
//3
listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).shuffled()[2]
//1
(0..10).shuffled().first()(0..10).shuffled()[5]

或是使用 random() 隨機取出一個值

listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).shuffled().random()

IntRange.random, Collection.random

這邊介紹的 random() 函式與前面所介紹的 IntRange.random() 是不同的函示。

看了原始碼得知,其實這兩個 random() 函式,最終都是呼叫到 Random 的 nextInt()。所以效果都是一樣的,可以依照自己的使用情境來選擇。

  • IntRange.random
@SinceKotlin("1.3")
public fun IntRange.random(random: Random): Int {
try {
return random.nextInt(this)
} catch(e: IllegalArgumentException) {
throw NoSuchElementException(e.message)
}
}
  • Collection.random
@SinceKotlin("1.3")
public fun <T> Collection<T>.random(random: Random): T {
if (isEmpty())
throw NoSuchElementException("Collection is empty.")
return elementAt(random.nextInt(size))
}

4. System.currentTimeMillis()

接下來的這個方法,比較奇耙一點,利用 System.currentTimeMillis() 取得以Million Second 表示的現在時間,接著取最後面的位數。

System.currentTimeMillis().toString().toCharArray().last().toInt()//Kotlin 1.5 以後
System.currentTimeMillis().toString().toCharArray().last().digitToInt()

不過嚴格說來,這個不是隨機產生出來的,只是看起來很像是隨機數而已。

結論

在 Kotlin 中,我們可以在 Random 類中使用 nextXXX 函式來隨機產生一組數字,並且還可以帶入起終值,讓產生的數值落在期待的區間中。

利用 Random 產生隨機數是屬於比較正規的方式,如果我們想要產生範圍內 Int 的隨機數,我們可以使用 IntRange 來建立一堆數字區間,並且使用 random() 隨機產生一個數字。

另外我們也可以使用任意的 List 、Set 來產生隨機數,這麼做的好處是,我們可以自行決定在集合裡面的數值是什麼,先使用 shuffled()將集合函式弄亂,在隨機從集合裡面取得一個值。

最後,附上非正規的做法,我們也可以使用 System.currentTimeMillis()來產生亂數,不過這樣可能不夠亂就是了。

本篇文章如果有幫助到你,請拍手👏鼓勵我吧~

--

--

Andy Lu

Android/Flutter developer, Kotlin Expert, like to learn and share.