1. 程式人生 > >18,rand('state',sum(100*clock))

18,rand('state',sum(100*clock))

原文連結:Matlab中rand('state',sum(clock))解析 - 火星十一郎 - 部落格園
https://www.cnblogs.com/hxsyl/p/4523988.html

Matlab中rand('state',sum(clock))解析

一.問題來源

  來自於一份PSO程式碼,PSO中需要初始化粒子位置和速度。

二.問題探究

  眾所周知,Matlab中的rand()函式產生的是偽隨機數,但一般用來也可以接受。但是,如果我們知道偽隨機數的初始狀態,那麼產生的偽隨機數是唯一確定的。問題來了,Matlab每次啟動會重置rand()和randn()的初始狀態(重置為0),也就是說,你產生的隨機數會出現兩次隨機數一模一樣的情況,如:

複製程式碼

 1 >> rand('state',0) 
 2 >> rand(3,1)
 3 
 4 ans =
 5 
 6     0.9501
 7     0.2311
 8     0.6068
 9 
10 >> rand(3,1)
11 
12 ans =
13 
14     0.4860
15     0.8913
16     0.7621
17 
18 >> rand('state',0)
19 >> rand(3,1)
20 
21 ans =
22 
23     0.9501
24     0.2311
25     0.6068

複製程式碼

  可以看到,第三次產生隨機數,因為初始狀態都是0,所以產生了完全一樣的隨機數!
設定初始狀態的好處是,只需要儲存那時的初始狀態再執行一遍程式你就可以重現之前的計算過程和結果。

  缺點是雖然程式使用了隨機數,但由於(每次啟動後)初始狀態一樣,實際執行出來卻是相同的重複過程,你需要人工設定一個保證隨機性的初始狀態。

三.問題分析

  計算機系統中的隨機數都是偽隨機數,是通過一個演算法連續產生的,知道上一個隨機數,下一個隨機數就確定,已知從給定的某個數開始,後面連續的隨機數序列都已經確定,我們使用隨機數就好像從這個序列中(也叫隨機數流)中取數字使用,為了增加隨機數的隨機程度,和可控性,用rand('state',X)來設定隨機數流的狀態,就像C語言中隨機數的seed,一旦給一個X值,那麼後面的隨機數流就確定,為了增加隨機性,這裡用當前時間數碼sum(clock)作為隨機數的狀態,clock返回一個6個元素的向量分辨是年月日時分秒,sum加起來就作為隨機數的狀態,因為你每次執行程式的時間不同,所以得到的隨機數序列就不同單獨使用這句時,改變了隨機數流的狀態,但是還沒有使用,所以不產生任何變數。但這個演算法有一個問題是,如果計算機太快的話,仍然會生成相同隨機數。可考慮用 rand('state',sum(clock)*rand(1))。

四.問題解決

4.1 如何設定初始狀態

1

2

3

rand('seed', S)

rand('state', S)

rand('twister', S)

  S是表示初始狀態的整數。
  seed、state、twister就比較奇怪,令人捉摸不透,不知道該選用哪個。這實際上是產生隨機數的不同演算法。

  seed表示採用v4版本的隨機數產生器,state是v5版本的隨機數產生器,最後的twister用的則是Mersenne Twister隨機數產生器。

  那麼具體該用哪一個呢?在新版本的語法說明中,Matlab給出了答案:前兩個隨機數產生器都是“flawed”,推薦大家使用twister隨機數產生器。

  此外,MathWorks公司意識到了這幾個引數可能會產生誤導,於是在新版本(2012及以後)的Matlab中更新了語法。

1

2

3

4

5

rng(1);

A = rand(2,2);

 

rng('shuffle')

A = rand(2,2);

  新版的Matlab預設採用Mersenne Twister隨機數產生器,rng(S) 函式表示設定初始狀態,rng('shuffle') 表示隨機分配一個初始狀態。

  所以現在只需要記住rng()函式設定初始狀態,然後用rand產生隨機數就可以了。

  然而,有時我們只需要“真正”的偽隨機數(不重複!),如何得到?

4.2 產生非重複隨機數

  用2012版本之後的使用者比較方便,在產生隨機數之前使用rng('shuffle')洗一下就可以(shuffle是洗牌的意思)。

對於舊版本的使用者,還不支援rng函式。以前一般是rand('state',sum(100*clock))來根據當前時間設定初始狀態,但時間始終是遞增的,而且變化幅度相對來說很小,效果不是很好。

  有很多人用別的方式設定初始狀態(如rand('twister', fix(mod(1e11*(sum(clock)-2009), 2^31)));),為簡便起見,個人推薦採用新版Matlab中rng函式語法,即rand('twister',mod(floor(now*8640000),2^31-1)) ,這樣可以產生的不同的隨機數。採用這種辦法大約每497天種子才會重複一次,一般使用的話足夠了。

  參考文獻:百度知道

  http://cn.mathworks.com/help/matlab/math/generate-random-numbers-that-are-different.html

打賞:為祖國開源事業添磚加瓦

作者:火星十一郎

出處:http://www.cnblogs.com/hxsyl/

本文版權歸作者火星十一郎所有,歡迎轉載和商用,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利.

分享到: 更多

分類: Mathematical Modeling