15

編集:私の主な質問は、TI-84 プラス RNG アルゴリズムを自分のコンピューターに複製して、Javascript や Lua などの言語で記述して、より高速にテストできるようにすることです。

エミュレーターを使ってみましたが、電卓より遅いことがわかりました。

関係者のために:このような別の質問がありますが、その質問への回答は、既に生成された数値をコンピューターに転送する方法を示しているだけです。私はこれをしたくありません。私はすでにそのようなことを試しましたが、週末中ずっと電卓を実行したままにしておく必要がありましたが、まだ完了していません.

4

3 に答える 3

21

使用されているアルゴリズムは、P. L'Ecuyer による論文「効率的でポータブルな複合乱数ジェネレーター」からのものです。

ペーパーはこちらから、無料でダウンロードできます

Ti 計算機で使用されるアルゴリズムは、p の RHS 側にあります。747. 写真を入れました。

レキュイエのアルゴリズム

これを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 が見つかりませんでした) エミュレーターから出力を得ました。

Ti-83 スクリーンショット

これは、私の実装が生成するものと一致します

私のコンピューター

実装の出力精度を上げただけで、次の結果が得られました。

0.9435973904
0.9083188494
0.1466878273
0.5147019439
0.4058096366
0.7338123019
0.04399198693
0.3393625207

これらは、重要度の低い桁で Ti の結果とは異なることに注意してください。これは、2 つのプロセッサ (Ti の Z80 と私の X86) が浮動小数点計算を実行する方法の違いかもしれません。もしそうなら、この問題を克服するのは難しいでしょう。それにもかかわらず、シーケンスは正確な整数数学のみに依存しているため、乱数は同じシーケンスで生成されます (以下の警告があります)。

また、型を使用してlong中間値を格納しました。Ti の実装が整数オーバーフローに依存しているというリスクがあります (私は L'Ecuyer の論文を注意深く読んでいませんでした)。その場合、int32_tこの動作をエミュレートするには、または同様の型に調整する必要があります。繰り返しますが、プロセッサが同様に機能すると仮定します。

編集

このサイトは、コードの Ti-Basic 実装を次のように提供します。

: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

これは、元の論文に基づく実装で達成されたものと一致します。

于 2015-09-25T21:35:43.170 に答える
3

TI-Basic コマンドで使用されるアルゴリズムは、 TIBasicDevrandによる L'Ecuyer のアルゴリズムです。

rand は、0 から 1 の間の一様分布の疑似乱数を生成します (このページや他のページでは、簡単にするために疑似接頭辞を省略する場合があります)。 rand(n) は、0 から 1 の間の一様分布の n 個の疑似乱数のリストを生成します。seed→rand組み込みの疑似乱数ジェネレーターをシード (初期化) します。工場出荷時のデフォルトのシードは 0 です。

L'Ecuyer のアルゴリズムは、TI 電卓で疑似乱数を生成するために使用されます。

残念ながら、テキサス・インスツルメンツがこの主張を裏付ける情報源を見つけることができなかったので、これが使用されたアルゴリズムであると確信することはできません. また、L'Ecuyer のアルゴリズムが正確に何を参照しているのかもわかりません。

于 2015-09-25T20:57:20.607 に答える