編輯:我的主要問題是,我想複製我的計算機上的TI-84加RNG算法,這樣我就可以像Javascript或Lua的語言寫,以測試它更快。TI-84 +隨機數生成算法
我試過使用模擬器,但事實證明它比計算器慢。
只針對有關人員:還有另一個question這樣,但回答這個問題只是說如何將已經生成的數字轉移到計算機。我不想要這個。我已經嘗試過類似的東西,但是我不得不讓計算器整個週末都運行,但仍然沒有完成。
編輯:我的主要問題是,我想複製我的計算機上的TI-84加RNG算法,這樣我就可以像Javascript或Lua的語言寫,以測試它更快。TI-84 +隨機數生成算法
我試過使用模擬器,但事實證明它比計算器慢。
只針對有關人員:還有另一個question這樣,但回答這個問題只是說如何將已經生成的數字轉移到計算機。我不想要這個。我已經嘗試過類似的東西,但是我不得不讓計算器整個週末都運行,但仍然沒有完成。
正在使用的算法來自紙張P.L'Ecuyer的高效便攜式組合隨機數發生器。您可以找到here的文件,並從here免費下載。
Ti計算器使用的算法位於p的RHS端。我已經收錄了一張照片。
我已經翻譯成一個C++程序
#include <iostream>
#include <iomanip>
using namespace std;
long s1,s2;
double Uniform(){
long Z,k;
k = s1/53668;
s1 = 40014*(s1-k*53668)-k*12211;
if(s1<0)
s1 = s1+2147483563;
k = s2/52774;
s2 = 40692*(s2-k*52774)-k*3791;
if(s2<0)
s2 = s2+2147483399;
Z=s1-s2;
if(Z<1)
Z = Z+2147483562;
return Z*(4.656613e-10);
}
int main(){
s1 = 12345; //Gotta love these seed values!
s2 = 67890;
for(int i=0;i<10;i++)
cout<<std::setprecision(10)<<Uniform()<<endl;
}
注意,初始種子s1 = 12345
和s2 = 67890
這一點。
,並得到從TI-83的輸出(對不起,我找不到一個TI-84 ROM)模擬器:
這符合什麼我實現生產
我剛剛開始執行我的輸出精度,並得到以下結果:
0.9435973904
0.9083188494
0.1466878273
0.5147019439
0.4058096366
0.7338123019
0.04399198693
0.3393625207
請注意,他們不同於Ti的結果中較不重要的數字。這可能是兩個處理器(Ti的Z80與我的X86)執行浮點計算的方式不同。如果是這樣,這將是很難克服這個問題。儘管如此,隨機數仍然會以相同的順序生成(下面的警告),因爲該順序僅依賴於整數數學,這是精確的。
我也用long
類型來存儲中間值。 Ti實現依賴於整數溢出存在一些風險(我沒有仔細閱讀L'Ecuyer的論文),在這種情況下,您必須調整爲int32_t
或類似的類型來模擬此行爲。再次假設處理器的表現類似。
編輯
This site提供的Ti-基本執行的代碼如下:
:2147483563→mod1
:2147483399→mod2
:40014→mult1
:40692→mult2
#The RandSeed Algorithm
:abs(int(n))→n
:If n=0 Then
: 12345→seed1
: 67890→seed2
:Else
: mod(mult1*n,mod1)→seed1
: mod(n,mod2)→seed2
:EndIf
#The rand() Algorithm
:Local result
:mod(seed1*mult1,mod1)→seed1
:mod(seed2*mult2,mod2)→seed2
:(seed1-seed2)/mod1→result
:If result<0
: result+1→result
:Return result
我翻譯這個成C++來進行測試:
#include <iostream>
#include <iomanip>
using namespace std;
long mod1 = 2147483563;
long mod2 = 2147483399;
long mult1 = 40014;
long mult2 = 40692;
long seed1,seed2;
void Seed(int n){
if(n<0) //Perform an abs
n = -n;
if(n==0){
seed1 = 12345; //Gotta love these seed values!
seed2 = 67890;
} else {
seed1 = (mult1*n)%mod1;
seed2 = n%mod2;
}
}
double Generate(){
double result;
seed1 = (seed1*mult1)%mod1;
seed2 = (seed2*mult2)%mod2;
result = (double)(seed1-seed2)/(double)mod1;
if(result<0)
result = result+1;
return result;
}
int main(){
Seed(0);
for(int i=0;i<10;i++)
cout<<setprecision(10)<<Generate()<<endl;
}
這給了以下結果:
0.9435974025
0.908318861
0.1466878292
0.5147019502
0.405809642
0.7338123114
0.04399198747
0.3393625248
0.9954663411
0.2003402617
它們與基於原始文件的實現相匹配。
TI-Basic rand
命令使用的算法是根據TIBasicDev的L'Ecuyer算法。
蘭特生成均勻分佈的僞隨機數( 此主頁等有時會下降爲簡單起見僞前綴) 0和1之間蘭特(n)的生成n的列表均勻分佈的僞隨機 數字在0和1之間。種子→蘭德種子(初始化) 內置僞隨機數生成器。出廠默認種子 爲0.
TI計算器使用L'Ecuyer算法生成 僞隨機數。
不幸的是,我一直沒有能夠找到德州儀器公佈的備份此聲明的任何源代碼,所以我不能肯定這是使用的algorthm。我也不確定L'Ecuyer算法提到的究竟是什麼。
'P. L'Ecuyer,「Combined Multiple Recursive Random Number Generators」,Operations Research,44,5(1996),816-822. –
該鏈接詳細描述了該算法:http://tibasicdev.wikidot.com/68k:randseed –
我在Python中實現了rand,randInt,randM和randBin。感謝理查德的C代碼。所有實施的命令按預期工作。你也可以在this Gist找到它。
import math
class TIprng(object):
def __init__(self):
self.mod1 = 2147483563
self.mod2 = 2147483399
self.mult1 = 40014
self.mult2 = 40692
self.seed1 = 12345
self.seed2 = 67890
def seed(self, n):
n = math.fabs(math.floor(n))
if (n == 0):
self.seed1 = 12345
self.seed2 = 67890
else:
self.seed1 = (self.mult1 * n) % self.mod1
self.seed2 = (n)% self.mod2
def rand(self, times = 0):
# like TI, this will return a list (array in python) if times == 1,
# or an integer if times isn't specified
if not(times):
self.seed1 = (self.seed1 * self.mult1) % self.mod1
self.seed2 = (self.seed2 * self.mult2)% self.mod2
result = (self.seed1 - self.seed2)/self.mod1
if(result<0):
result = result+1
return result
else:
return [self.rand() for _ in range(times)]
def randInt(self, minimum, maximum, times = 0):
# like TI, this will return a list (array in python) if times == 1,
# or an integer if times isn't specified
if not(times):
if (minimum < maximum):
return (minimum + math.floor((maximum- minimum + 1) * self.rand()))
else:
return (maximum + math.floor((minimum - maximum + 1) * self.rand()))
else:
return [self.randInt(minimum, maximum) for _ in range(times)]
def randBin(self, numtrials, prob, times = 0):
if not(times):
return sum([(self.rand() < prob) for _ in range(numtrials)])
else:
return [self.randBin(numtrials, prob) for _ in range(times)]
def randM(self, rows, columns):
# this will return an array of arrays
matrixArr = [[0 for x in range(columns)] for x in range(rows)]
# we go from bottom to top, from right to left
for row in reversed(range(rows)):
for column in reversed(range(columns)):
matrixArr[row][column] = self.randInt(-9, 9)
return matrixArr
testPRNG = TIprng()
testPRNG.seed(0)
print(testPRNG.randInt(0,100))
testPRNG.seed(0)
print(testPRNG.randM(3,4))
你能說清楚你的意思是「有人知道TI-84 plus計算器上的RNG是如何工作的嗎?」我不明白你想要做什麼。你想知道它是如何播種的嗎?你想知道分配是多麼隨機的嗎?你提到你跑了一個很長的測試,但沒有明確的問題。 – Dan
我編輯了這個問題。 – tupperkion
所以你試圖'測試'?目前還沒有100%清楚你在這裏做什麼。你*不*只是想要很多像其他問題一樣的隨機樣本? – Dan