擬似乱数生成について

このQ&Aのポイント
  • 擬似乱数生成についての疑問を解説します。
  • 線形合同法を用いた擬似乱数生成の仕組みと次の乱数値の計算方法を解説します。
  • 擬似乱数生成において、既知の値から次の乱数値を計算する方法について説明します。
回答を見る
  • ベストアンサー

擬似乱数生成について

お世話になります。 下記、問題について教えてください。   ============ 問題 =============   線形合同法はA,C,Pを秘密の定数(Pは素数),初期値をR1として下記演算によって計算される系列 R1,R2,R3・・・・を擬似乱数として用いる。 R_{i} = A・R_{i-1} + C (mod P) このアルゴリズムと素数Pがわかっているとき、いくつの乱数値がわかれば次の乱数値が計算できるか?その理由も示せ。   ============================= 自分なりに調べてやってみたのですが、いまいちよくよく分かりません。 直感的に、未知数が3個あるので連続した3つの乱数値を各Rとして代入すれば、2元1次方程式を得られ、A,Cが決定できると思ったのですが、どうもうまくいかない・・・ 暗号理論の専門書を読んでみたところ、やはりPが判明いてる場合、連続した3つの値で良いようです。もしPが判明していない場合でも、4つ以上の連続した値から次の乱数値が分かるそうです。 完全に混乱しています。どなたか分かる方、解説していただけませんか。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • R_Earl
  • ベストアンサー率55% (473/849)
回答No.2

> (mod P)同士の加算を一般的に示すと > A(mod P)+B(mod P)において、A=4,B=5,P=3とした場合 > (与式)= 4(mod 3) + 5(mod P) = 1 + 2 = 3 > 上記の演算が可能ならば、 > (与式) = 4 + 5 (mod 3) = 9 (mod 3) = 0 ≠ 3 > 反証があることから、(1)の仮定は成立しない。 > > となるのではないでしょうか? 3を法とする合同式なら、3と0は合同です。 なので一つ目の式も、二つ目の式も、同じ値を意味しています。 それから、計算中に(mod 3)を0個にするのはだめです。 それでは、合同式ではなくなってしまいます。 おそらく、質問者さんは合同式でつまづいているのではないでしょうか? modはある意味、+や×のような演算子とは別物です。 例えば、a = b (mod N)という合同式では、(mod N)は左辺と右辺両方に作用します。 つまり4 = 7 (mod 3)のような式もOKということです。 (左辺を3で割ると余り1、右辺を3で割ると余り1なので合同) 一つ目の式 > (与式)= 4(mod 3) + 5(mod P) = 1 + 2 = 3 は、正確にはこうなります。 (与式)= { 4(mod 3) + 5(mod 3) } (mod 3) = 1 + 2 (mod 3)= 3 (mod 3) = 0 (mod 3) 二つ目の式 > (与式) = 4 + 5 (mod 3) = 9 (mod 3) = 0 も、正確にはこうなります。 (与式) = 4 + 5 (mod 3) = 9 (mod 3) = 0 (mod 3) 最後の最後まで(mod 3)が無くならない点に注意して下さい。 > また、試しに行っていただいた乱数についてですが、 > 乱数を発生させる過程において、事前にA,C,Pを定めておく必要があるはずだと思うんですが、R_{1}以降のR_{2},R_{3}はこのアルゴリズムに従っていますか? R_{1} = 3に関しては適当に決めましたが、それ以外は R_{i} = 4R_{i-1} + 2 (mod 13)に従っています。 R_{2} = 4R_{1} + 2 (mod 13) R_{2} = 4 × 3 + 2 (mod 13) R_{2} = 14 (mod 13) R_{2} = 1 (mod 13) R_{3} = 4R_{2} + 2 (mod 13) R_{3} = 4 × 1 + 2 (mod 13) R_{3} = 6 (mod 13)

参考URL:
http://ja.wikipedia.org/wiki/%E5%90%88%E5%90%8C%E5%BC%8F
golive001
質問者

お礼

ご返信ありがとうございました。 >>おそらく、質問者さんは合同式でつまづいているのではないでしょうか? おっしゃる通りです。この○を法として・・・といった部分が感覚的によく分からなかったんです。(特に演算の仕方が・・(汗)) URLも今後、参考にしてもう少し自分で理解できるようにしたいと思います。 また何かございましたら、ぜひよろしくお願いいたします。 丁寧な解答をありがとうございました!!

その他の回答 (1)

  • R_Earl
  • ベストアンサー率55% (473/849)
回答No.1

乱数には詳しくないのですが、 似たような分野に少し取り組んでいるので、分かる範囲で答えてみます。 R_{i} = A・R_{i-1} + C (mod P)の形が、 高校数学の数列でやった、a_{n+1} = 2a_{n} + 1のような漸化式に似ているので、 その時に使った方法で考えてみます。 まず、次の式を用意します。 R_{i} = A・R_{i-1} + C (mod P) R_{i-1} = A・R_{i-2} + C (mod P) 左辺は左辺同士、右辺は右辺同士で引き算すれば、 R_{i} - R_{i-1} = A(R_{i-1} - R_{i-2}) (mod P) となります。これでCの無い式に変形できました。 R_{i}, R_{i-1}, R_{i-2}の3つの値が分かるなら、 この方程式からAが決定できるはずです。 次に既知の乱数値とAを用いて、 R_{i} = A・R_{i-1} + C (mod P)の式からCを求められるはずです。 試しにR_{i} = 4R_{i-1} + 2 (mod 13)で実際に乱数を作ってみて A、Cが決定できるのか試してみました。 R_{1} = 3 (適当に決めました) R_{2} = 1 R_{3} = 6 です。 R_{i} - R_{i-1} = A(R_{i-1} - R_{i-2}) (mod P)にあてはめて 6 - 1 = A(1 - 3) (mod 13) 5 = -2A (mod 13) 5 = 11A (mod 13) これを満たすAは、A = 4。 R_{i} = A・R_{i-1} + C (mod P)にA = 4, i = 3を代入して、 6 = 4 × 1 + C (mod 13) 6 = 4 + C (mod 13) ∴C = 2 というわけで、AとCが求められました。 一応、R_{1}~R_{4}でも試してみましたが、こちらでも同じ結果がでました。 間違っている点がありましたらご指摘下さい。

golive001
質問者

お礼

詳細なご解答ありがとうございました。 早速なんですが、 まず、下記の式は間違っているような気がします。 >> R_{i} - R_{i-1} = A(R_{i-1} - R_{i-2}) (mod P)・・・(1) (mod P)同士の加算を一般的に示すと A(mod P)+B(mod P)において、A=4,B=5,P=3とした場合 (与式)= 4(mod 3) + 5(mod P) = 1 + 2 = 3 上記の演算が可能ならば、 (与式) = 4 + 5 (mod 3) = 9 (mod 3) = 0 ≠ 3 反証があることから、(1)の仮定は成立しない。 となるのではないでしょうか? また、試しに行っていただいた乱数についてですが、 乱数を発生させる過程において、事前にA,C,Pを定めておく必要があるはずだと思うんですが、R_{1}以降のR_{2},R_{3}はこのアルゴリズムに従っていますか? 質問ばかりですみません。 お時間のある時にでも、ご解答いただけますと幸いです。

関連するQ&A

  • ハッシュを使った擬似乱数

    予測不能な擬似乱数列を生成する際に、よく一方向ハッシュの性質を利用する 場合があります。一方向ハッシュの生成源として内部状態が与えられますが、 内部状態のbitサイズはどの程度にしたらよいでしょうか?   [種(カウンタの初期値)]        |        |        ↓ ┌→[内部状態(カウンタ)]―┬―→(一方向ハッシュ)――→擬似乱数列 |                 | |                 ↓ |               [1増加] |                 | └―――――――――――┘ ※ 暗号技術入門 秘密の国のアリス 結城 浩 著      ――第12章 乱数 Fig.12.5 より 極端な例として鍵(種)のサイズを32bit(C言語でunsigned long型)、値を0とします。 |0000 0000|0000 0000|0000 0000|0000 0000| 上記の値でハッシュ値を取ります。ハッシュアルゴリズムがSHA1の場合、 以下のような値が得られます(と思います)。 a = -1099956234 b = -343932961 c = -1287651379 d = -84150665 e = -1099170433 これらの値から鍵の値を得ることは困難なので、ハッシュ値によって生成された 擬似乱数は予測不能であるといえます。また、鍵の値を1だけ加算させて次の擬似乱数 を生成します。一般的にこのようにして乱数列は生成されます。 上記の例では32bitのとり得る値は0~4294967295です。鍵の値を一つずつ試し ていけば、それほど時間をかけることなく乱数の予測不能性は破られてしまいます。 ここで鍵の値を256bitとしました。 |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| しかしこれだと1加算しただけではビット全体に対して変化が少なすぎます。 |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0001|← 2005年に中国の大学の研究チームによってSHA1の弱衝突耐性が破られてしまいました。 現段階ではSHA1に変わる新しいアルゴリズムは発見されていません。(SHA2が作られましたが、 これはSHA1のbit数を拡張しただけで基本設計は変わっていません)なのでハッシュ値を 生成させる値もなるべく変化に富んだ値を与えることが推奨されています。 まとめると、   ・鍵(種)を総当り攻撃されないようにbit数を大きくしなけらばならない。   ・bit数を大きくすると1加算したときに変化が小さすぎる。   ・最初の図の手法は同記の文献に書いてあったもので、なるべく変えたくない。    (実際に使われる手法はある程度保障されているから) の制約があります。なので”bit数をどの程度にしたら適当か???”というのが質問です。 また、これらの問題を打開する方法もあればよいのですが、、、

  • 一様乱数?疑似乱数?

    0.0以上~1.0未満の範囲のdouble型一様乱数rdmを1000個発生させて、ヒストグラムをつくりたいのですが、このような書き方で良いのか、ご教示願えませんでしょうか。 ヒストグラムと言っても、グラフではなく、区間0≤u<0.1、0.1≤u<0.2、…、0.9≤u<1.0の10区間とし、配列aaに格納しているだけです。 また、「Math.random」を用いるやり方は理解できるのですが、下記のような書き方はいまいち納得できません。 疑問点1つ目、前者は毎回発生する乱数が違うのに、後者は同じですよね?なぜでしょうか。後者は毎回決まった値が出るので、初期値(seed)から決まった計算をしているということでしょうか。 疑問点2つ目、//kokoの次の行に x = rdm.nextDouble(); のように発生させた乱数を一時的に入れておかなくてもよいのでしょうか。 import java.util.*; public class test { public static void main(String [] args) { int aa [] = new int [10]; long seed = 999L; Random rdm = new Random(); rdm.setSeed(seed); for(int i = 0; i < 1000; i++){ for(int j=1; j<=10; j++){//koko if(rdm.nextDouble() < ((j-1)*0.1) && rdm.nextDouble() >= (j*0.1)) aa[j-1] = aa[j-1] + 1; } } for(int i=0; i<10; i++){ System.out.println( aa[i] ); } } }

    • ベストアンサー
    • Java
  • 重複しない乱数の生成

    他の質問での回答に対してもう少し具体的に知りたいと思って投稿しました。 自分はいわゆる日曜プログラマです。 勉強のつもりでOKWebのコンピュータ関連でいろいろ回答してます。 (未熟者なのでとんちんかんなのが多いですが) で次の質問に回答しました。内容は「重複しない乱数を発生させる方法」です。 http://okweb.jp/kotaeru.php3?q=1239644 私が回答したのは#10です。私の考えは 1. 最初に配列に重複しない値を入れ(1から100を順番に) 2. 2要素の値を入れ換える 3. 2を任意の回数繰り返す 4. 配列の先頭から値を取り出す という考えです。 が、そのあと#12の回答があり、それを読むと私の方法ではマズイようです。 「どうしてマズイのか」ということはなんとなくわかった(ような)気がするんですが、 では「具体的にどうすべきなのか」が知りたいです。 違う方法として自分ではこう考えました。 上記1の配列(これを配列Aとする)と同じ要素数(ここでは100個)の配列Bを作って 1. 0~(配列Aの要素数 - 1)の範囲で乱数を発生させる -> 得られた数値をnとする 2. 配列A[n]の値を配列Bに入れる -> 最初は配列B[0]に入れる 3. 配列A[n]を削除 -> 要素数が1個減る 以下これを繰り返し、配列B[99]まで入れて終了。 過去の質問を覗いてみましたが、いろいろな方法があってどれがいいのか迷ってきま した。どちらかというと具体的なソースではなく考え方を教えてください。 よろしくお願いします。

  • 乱数について

    今、あるデータの順番をばらばらにするプログラムを作ろうとしています。  たとえば、a,b,c,dとあったら、d,b,c,aとするように、この時考えられるプログラムは、データの数だけ配列を用意して、乱数で、どのデータを出力させるかを決定し、出力し終わったら、その配列のところに印を立てて、次にくるデータに対して、2重にならないように順次、出力していく方法が考えられるのですが。。。    膨大なデータをこのように、すると、二重になる確立が出力するたびに、高くなっていって、なかなか終わらなくなってしまいます。  そこで、残ったデータから、ランダムに選び出すアルゴリズムまたは、関数はないでしょうか?よろしくお願いします。

  • 2つの乱数列の生成について

    C言語でプログラミングをしています. 質問ですが,以下のような2つのプログラムがあったとします. /*プログラム1*/ for(i=0;i<=100;i++){ r = rand(); /* 乱数rを用いた操作を実行 */ } /*プログラム2*/ for(i=0;i<=100;i++){ r = rand(); /* 乱数rを用いた操作を実行 */ for(j=0;j<=10;i++){ s = rand(); /* 乱数sを用いた操作を実行 */ } } 上記の2つのプログラムにおいてiの値が同じ時にrの値を同じにしたいのです. 2つの種から同時に別の乱数列を発生できるなら容易に実現できるとは思うんですが,そのような方法はあるのでしょうか. また,別の方法で実現することはできるのでしょうか. 分かる方がいらっしゃいましたら,ぜひ回答をお願いします.

  • ある乱数生成法により,生成した最初の乱数の値は固定するか確かめて頂きた

    ある乱数生成法により,生成した最初の乱数の値は固定するか確かめて頂きたいです. 0.0から1.0までの一様乱数を発生させる方法です. C言語のコードは以下に載せます. #define IA 16807 #define IM 2147483647 #define AM (1.0/IM) #define IQ 127773 #define IR 2836 #define MASK 123459876 float ran0(long *idum) { long k;   float ans; *idum ^= MASK; k=(*idum)/IQ; *idum=IA*(*idum-k*IQ)-IR*k; if (*idum < 0) *idum += IM; ans=AM*(*idum); *idum ^= MASK; return ans; } この乱数生成法をBVAで,計算の中で繰り返し用いようとしています. idumを任意の整数値に設定・再設定すれば乱数列が初期化されると書いてあったため,idumの値を変えてみましたが,生成された乱数の最初の値は固定されたままでした. そこで,もともとこの乱数生成法がそのようになっているのかを教えて頂きたいです. よろしくお願いします.

  • 乱数について

    こんばんは。 何度も申し訳ありませんが、今回は乱数について教えてください。 LinuxでCを勉強しているんですが、 randで乱数を発生させることはできたんですが、 そのプログラムを何度実行させても 出てきた乱数は同じ値なんです。 プログラム内で例えば10こ乱数を発生させたとすると 違うものが出ます。 しかし、もう一度そのプログラムをはしらせると 前回と全く同じ並びで同じ数が出るのはどうしてでしょうか? 言ってる意味わかっていただけましたでしょうか? 宜しくお願いします。

  • 足して100になるような乱数のアルゴリズム

    次のような、8つの変数にそれぞれランダム(0から100まで)に発生させた数を入れて 毎回合計で100になるようにしたいです。 a[0] = 12; a[1] = 21; a[2] = 8; a[3] = 30; a[4] = 0; a[5] = 14; a[6] = 5; a[7] = 10; もう1回実行したとしても a[0] = 2; a[1] = 14; a[2] = 62; a[3] = 5; a[4] = 0; a[5] = 0; a[6] = 1; a[7] = 16; と合計で100になります。 a[0] = 0; a[1] = 0; a[2] = 100; a[3] = 0; a[4] = 0; a[5] = 0; a[6] = 0; a[7] = 0; と滅多にありないですけど、このようになる可能性もあると思います。 このような乱数を発生させるためにはどのようなアルゴリズムになるのでしょうか?

  • 乱数について

    乱数の分布を見るために以下のようなプログラムを書きました。 #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int i,imax, S[RAND_MAX], r; double x,y; FILE *output1; output1=fopen("random2.data","w"); imax=100000; for(i=0;i<=imax;i++){ r = rand(); S[r] += 1; } for(i=0;i<=RAND_MAX;i++){ fprintf(output1,"%d %d \n",i,S[i]); } return 0; } するとコンパイルできて実行もできるのですが、なぜか乱数が30000を 超えるくらいのところでおかしな値になりました。 原因がわからないのでどなたか教えてください。

  • JAVA 乱数で同じ数字を出さない方法

    JAVAで乱数を使いたいのですが、同じ数を出さない方法が今一度 わかりません。 プログラムはサーブレットで記述しており、ブラウザで「数を出す」ボタンがおされたら、リクエストを受けたサーブレットは、一つ、1~10までの数を出し表示はJSPです。そしてまたボタンが押されたら、一つ、1~10までの数を出します。 以下に今のサーブレットに記述してあるプログラムの状態を書かせていただきますので、同じ数字を出さない方法が何かございましたら教えてください。宜しくお願いします。 long seed = System.currentTimeMillis(); //時間で乱数値をとる Random r1=new Random(seed); //乱数ジェネレータを作成する int i; i = r1.nextInt(10)+1;//入力された命令回数をint型に変換し1から10までの数が出されiに入る。

    • ベストアンサー
    • Java