Board logo

標題: 自己寫 自己的方式產生亂數 [打印本頁]

作者: sjgau    時間: 2013-10-26 03:59     標題: 自己寫 自己的方式產生亂數

一秒鐘,可以執行督少個 家法的運算?

一秒鐘,可以產生多少個亂數?

餐猜看
作者: sunnyso    時間: 2013-10-26 08:13

回復 1# sjgau


  期待解說
作者: sjgau    時間: 2013-10-26 09:51

回復 2# sunnyso


    先解釋,為何要 自己寫

一 自己生的小孩,才可以打

二 從寫作的 過程,可以發現很多問題和 學問

敬請期待
作者: sunnyso    時間: 2013-10-26 10:05

回復 3# sjgau

期待ing + 關注ing
作者: c_c_lai    時間: 2013-10-26 12:18

本帖最後由 c_c_lai 於 2013-10-26 12:23 編輯

回復 4# sunnyso
VBA Function Example

The RND function can only be used in VBA code in Microsoft Excel.
Here are some examples of what the RND function would return:
  1.     Int ((10 - 1 + 1) * Rnd + 1)     '   傳回介於 1 到 10 間的亂數值
  2.     Int ((200 - 100 + 1) * Rnd + 100)   '  傳回介於 100 到 200 間的亂數值
  3.     Int ((600 - 300 + 1) * Rnd + 300) '  傳回 介於 300 到 600 間的亂數值
複製代碼
For example:
  1. Sub Demo()
  2.     Dim retNum As Integer

  3.     retNum = Int ((300 - 200 + 1) * Rnd + 200)
  4.     MsgBox "retNum 的亂數值 = " & retNum
  5. End Sub
複製代碼
In this example, the variable called retNum would now contain a random number between 200 and 300.
作者: sjgau    時間: 2013-10-26 12:26

不准 使用 rnd
作者: ML089    時間: 2013-10-26 21:19

回復 6# sjgau


  亂數不准使用 rnd 要如何使用 ? 期待
作者: sjgau    時間: 2013-10-27 04:16

http://en.wikipedia.org/wiki/Linear_congruential_generator

上面所介紹的是 目前很流行的產生亂數的方法之一
線性同餘。
我習慣使用 Apple Lab. 的係數
R(n)= (R(n-1)*A + B) MOD C

A= 7^5= 16807,
B= 0
C= (2^31) - 1 = 2147483647
作者: sunnyso    時間: 2013-10-27 12:09

回復 8# sjgau

不是很懂, 可否用vba 寫一段code? 謝謝
作者: sjgau    時間: 2013-10-29 05:01

回復 9# sunnyso


    OK

等我 11/8 日本回來 再說
作者: sunnyso    時間: 2013-10-30 12:40

回復 10# sjgau

thanks in advance
作者: sjgau    時間: 2013-10-30 13:47

回復 11# sunnyso


    integer 的範圍,只有到 +32767, 不行使用

long 的範圍,雖然有到 +2147483647
但是,下一個 亂數,等於 前一個亂數,乘上 a, a= 7^5= 16807
就爆掉了

所以,必須使用 double,

single 的精確度,只有 2^24, 大約是 10^7, 不夠使用
所以,必須使用 double

當然,必須 反覆測試 每一個 細節
作者: stillfish00    時間: 2013-10-31 14:14

回復 8# sjgau
自己寫真的可以發現很多問題,學到很多,
希望能拋磚引玉,我是採用Microsoft Visual Basic 的那組參數,仿造rnd函數一樣傳回single。
  1. Function myRnd(Optional Number) As Single
  2.   Dim tmp As Double
  3.   'LCG Algorithm:
  4.   '  X(n+1) = (a * X(n) + c) mod m
  5.   Const a As Long = 1140671485
  6.   Const c As Long = 12820163
  7.   Const m As Long = 16777216  '2^24
  8.   Const x0 As Long = 1     '根據你使用哪組參數,x0有時有需要符合的條件。
  9.   
  10.   Static seed As Variant
  11.   '利用IsEmpty判斷,來初始化一 static變數為非零值。
  12.   If IsEmpty(seed) Then seed = x0
  13.   
  14.   '利用IsMissing判斷 optional 參數是否傳入,若函數有傳入參數時,設為種子。
  15.   If Not IsMissing(Number) Then seed = Number
  16.    
  17.   'myRnd = (a * seed + c) Mod m
  18.   '(a * seed + c)過大時,mod 會發生溢位,只能用其他方法求。
  19.   
  20.   tmp = a * seed + c  'double
  21.   seed = tmp - m * Fix(tmp / m)   '即計算 (a * seed + c) Mod m,此為產生的亂數值,並設為下次種子
  22.   myRnd = seed / m  '使傳回亂數值介於0到1之間
  23. End Function
複製代碼

作者: stillfish00    時間: 2013-11-1 08:16

本帖最後由 stillfish00 於 2013-11-1 08:20 編輯

回復 13# stillfish00
實測後仍不滿意,呼叫m次後,不會回到第一組產生的隨機數,
主因是 tmp = a * seed + c 即便是 double 數仍存有精確度誤差...   

LongLong又只有在64位元平台上可以使用
作者: c_c_lai    時間: 2013-11-1 09:11

回復 14# stillfish00
這是我測試的結果:
A.  rng = myRnd(sngVal)
[attach]16529[/attach]
B.  rng = myRnd(sngVal, 2 ^ 32)
[attach]16530[/attach]
略加增修部分:
  1. Option Explicit

  2. Sub Ex()
  3.     Dim sngVal As Single, rng As Range, xi As Long
  4.    
  5.     With Sheets(1)
  6.         .Cells.Clear
  7.         
  8.         For xi = 1 To 5
  9.             Set rng = .Range(Chr(64 + xi) & "1")
  10.             For sngVal = 1 To 20
  11.                 '  rng = myRnd(sngVal)
  12.                 rng = myRnd(sngVal, 2 ^ 32)
  13.                 Set rng = rng.Offset(1)
  14.             Next sngVal
  15.         Next xi
  16.         .Columns.AutoFit
  17.     End With
  18. End Sub

  19. Function myRnd(Optional Number, Optional m As Double = 2 ^ 24) As Single
  20.     Dim tmp As Double
  21.     '  LCG Algorithm:
  22.     '      X(n+1) = (a * X(n) + c) mod m
  23.     Const a As Long = 1140671485
  24.     Const c As Long = 12820163
  25.     '  Const m As Long = 16777216    '  2^24
  26.     Const x0 As Long = 1         '  根據你使用哪組參數,x0有時有需要符合的條件。
複製代碼

作者: stillfish00    時間: 2013-11-1 09:51

回復 15# c_c_lai
其實我的意思是這樣:
  1. Sub EX()
  2.   Dim a As Single, b As Single
  3.   Dim i
  4.   
  5.   a = Rnd
  6.   For i = 2 To 16777216
  7.     Rnd
  8.   Next
  9.   b = Rnd
  10.   Debug.Print a, b
  11.   
  12.   a = myRnd
  13.   For i = 2 To 16777216
  14.     myRnd
  15.   Next
  16.   b = myRnd
  17.   Debug.Print a, b
  18.   
  19. End Sub
複製代碼
像rnd一樣,這m次取的亂數都會不一樣,
但rnd取完m次後,再取下一次時,會回到第一次取的值,再一次循環。
就像LCG裡面提到的生命週期
作者: sjgau    時間: 2013-11-1 13:18

比較好的 亂數產生器的 條件
一 產生的計算速度 越快越好

二 亂數的範圍和 個數,越大越好


三 盡可能的 接近均勻分配

四 在產生下一個 相同的亂數之前,要把所有的亂數都跑過一遍


五 循環的週期要 固定

六 循環的 週期要 越大 越好
作者: sunnyso    時間: 2013-11-10 09:50

回復 10# sjgau

不知大大的日本之旅如何?

有空 麻煩指導這個亂數

謝謝
作者: sjgau    時間: 2013-11-10 12:17

回復 18# sunnyso


    11/8 回國
這兩天,在台大有授課的 行程
需要 明天 才能 開始
作者: sjgau    時間: 2013-11-10 12:18

回復 19# sjgau


    http://www.csie.ntu.edu.tw/train/teacher_display.php?num=18
我在 台大ˇ呃 課程介紹網頁
作者: stillfish00    時間: 2013-11-13 10:19

回復  stillfish00
實測後仍不滿意,呼叫m次後,不會回到第一組產生的隨機數,
主因是 tmp = a * seed +c  ...
stillfish00 發表於 2013-11-1 08:16


後來改為 tmp = (a mod m) *( seed mod m) + c 即可,
產生之模數不變,又因m = 2^24時, tmp為小於2^49之整數,
double之精確度可完整表示,不會有誤差。
#16 測試也可正常循環。




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)