1. 程式人生 > >關於隨機數不得不說的一個方法

關於隨機數不得不說的一個方法

隨機數,接觸程式時就會接觸到他,第一次知道隨機數隱約記得是和同學在討論彩票搖獎時知道的,現在看著自己那一把厚厚的彩票就知道當時有多天真了,天真的以為那玩意真隨機。好了,言歸正傳。

幾乎我接觸過的每一種語言都提供產生隨機數的系統方法,我平時用的時候直接拉來用了,今天突然看見群裡有人在問,就想著那就研究到底,看看random到底是個什麼鬼。

產生隨機數的方法:

Random屬於system下的類,想仔細研究,那就F12戳進去,看看他都有什麼方法。

Next()方法用來返回一個隨機數。同樣的程式碼你執行和我的結果很可能不一樣,而且我多次執行的結果也很可能不一樣,這就是隨機數。

1、不是bugbug

當我想使用上面的方法生成多個隨機數時,我自然而然的想到了for迴圈,於是我就迴圈一百次,生成100個隨機數,但結果讓我有點卵碎。

<pre name="code" class="csharp">if (Input.GetKeyDown(KeyCode.T))
        {
            for (int i = 0; i < 100; i++)
            {
                System.Random rand = new System.Random();
                Debug.Log("隨機數 = " + rand.Next());
            }
        }


你會發現,出現了大量的重複數字。這還真是見了鬼了。於是我想著rand就是個物件,為什麼要每次去例項化,看網上說可以把例項化的程式碼放在for迴圈外邊,試了試:

 if (Input.GetKeyDown(KeyCode.T))
        {
            System.Random rand = new System.Random();
            for (int i = 0; i < 100; i++)
            {
                Debug.Log("隨機數 = " + rand.Next());
            }
        }


還真歐克了

 

2、Why出現重複的現象:

這得扯一扯計算機生成隨機數的原理了,隱約記得之前瞭解過“隨機種子”的概念,於是百度了下,原理是生成隨機數的演算法有很多種,最簡單也是最常用的就是 "線性同餘法": n+1個數=(n個數*29+37) % 1000而“n個數”就稱之為隨機種子,而重複的根本原因就是預設的隨機種子是CPU時鐘,現在硬體這麼發達,一微妙執行幾遍函式都不是問題,所以同一時間段,出現多個重複的隨機數也就能理解了。我用程式碼解釋一下公式吧,MyJiLeiRandom自定義的一個功能極其雞肋的生成隨機數的類,你呼叫Next()就會給你生成雞肋的隨機數

public class MyJiLeiRandom
{
    private int seed = 2;
    public int Next()
    {
        int next = (seed * 29 + 37) % 1000;
        seed = next;
        return next; 
    }
}


他的確看起來是隨機的:

 

那我們平時怎麼讓這個雞肋的隨機數真的很隨機呢,其實有很多辦法,比如讓隨機種子等於遊戲自開啟以來執行的時長、當前使用者滑鼠在螢幕上的座標、設定本機處理器ID+啟動時長-滑鼠座標.x*滑鼠座標.y。各種方法,就怕你把自己也搞隨機了。

用場景載入時長來作為“隨機種子”,來產生看似“真正”的隨機數。

 if (Input.GetKeyDown(KeyCode.Y))
        {
            MyJiLeiRandom myRand = new MyJiLeiRandom();
            myRand.seed = (int)Time.timeSinceLevelLoad * Screen.currentResolution.height;
            
            for (int i = 0; i < 100; i++)
            {
                Debug.Log("雞肋類隨機數 = " + myRand.Next());
            }
        }


關於真隨機數,看過一個帖子,它確實生成了,它主要依據當前程序Id、當前執行緒Id、系統啟動後的TickCount、當前時間、QueryPerformanceCounter返回的高效能計數器值、使用者名稱、計算機名、CPU計數器的值等等來計算。不過一般的專案上確實用不到,如果要用,可自行百度。但萬變不離其宗,無非是把“隨機種子”搞的幾乎不可能重複。