プロが教えるわが家の防犯対策術!

cのrand()関数を使用せずに、
16bitの整数演算で、乱数を生成したいのですが、
何か良い方法はありませんでしょうか?
以下のように作ってみたのですが、時と場合によっては、
繰り返しになるみたいです。
なお、8bitのPICマイコンを使用しております。

宜しくお願い致します。

****longを2バイトとする。***
#define _ULONG unsgined long
_ULONG g_ulSeed = 31;
_ULONG rand2()
{
_ULONG ulTemp;
g_ulSeed = ( 2045 * g_ulSeed ) % 32768;
g_ulSeed = g_ulSeed % 0xfff0;

     // 上位8bitと下位8bitの入れ替え
ulTemp = ( g_ulSeed & 0xff ) << 8;
g_ulSeed = ulTemp | (g_ulSeed >> 8 );

return g_ulSeed;
}

A 回答 (3件)

★アドバイス


・簡単な数式を使って擬似乱数を作ります。
 下にその一例を載せます。
 数式を可変するといろいろと乱数が変わります。

サンプル:
unsigned int MyRand( unsigned long init )
{
 static unsigned long seed;
 
 if ( init != 0 ){
  seed ^= init;
 }
 seed *= 128945376;
 seed += 35;
 return (unsigned int)((seed >> 12) & 0xFFFF);
}

その他:
・MyRand() 関数の第一引数の初期値を与えると最初の乱数が別の数になります。
 特に指定しない場合は 0 を指定して下さい。
・適当な数 128945376 を掛けて 35 を足して long 型の 32 ビットから適当な 16 ビットを
 戻り値としています。この辺は自由にカスタマイズして下さい。
・以上。

この回答への補足

すみません。質問者です。
お礼の欄に記述できないようですので、
ここに記します。
乱数の計算はやっているみたいなのですが、
どうもseed *= 128945376;の計算が重いらしく、
不安定な動作になってしまいます。
せっかく、教えていただいたのに、
すみません。

補足日時:2007/07/04 18:35
    • good
    • 0
この回答へのお礼

ありがとうございます。
処理能力が低いマイコンを使用しておりますので、
seed *= 128945376;
の部分がうまくいくかどうか分かりませんが、
早速、実行してみます。

後で、結果をご報告します。

お礼日時:2007/07/04 18:16

M系列乱数



・t1,t2は基となる値(seed)の指定された位置のビットの状態。下記の例では2と5を使いました。
・この2つのエクスクルーシブORをとり、seedを1ビットシフトしてできたすき間(下記の例では最下位ビット)にいれる。

このくり返しです。
ただしseedの初期値は0以外を使う必要があります。(0で始めると1以外の値が出力されません)

論理演算だけなので速い(軽い)はずです。

-------------- ここから ----------------------------------

#include <stdio.h>

unsigned short NewRandom(unsigned short r)
{
unsigned short t1,t2;

t1 = (r&(1<<2))?1:0;
t2 = (r&(1<<5))?1:0;

r <<= 1;
r |= (t1^t2);

return r;
}


int main(void)
{
unsigned short r=0xabcd;

while ( 1 )
{
r = NewRandom(r);
printf("%04x\n",r);
}
return 0;
}
    • good
    • 0
この回答へのお礼

非常に、シンプルですね。
M系列って、聞いた事はありますが、
難しそうで、理解していません。
確か、乱数周期が、他の方法に比べて
長いのですよね。

ただ、試しに、vc++で動かしてみましたが、
なぜか途中で計算されなくなってしまいました。
PICマイコンでは動きました。
原因を考えてみます。
ありがとうございました。

お礼日時:2007/07/05 21:37

★アドバイス


>8bitのPICマイコンを使用しております。
 ↑
 8Bit なので 32Bit の long 型は重くなるのですね。
 では 16Bit 版を紹介します。

サンプル:
unsigned int MyRand( unsigned int init )
{
 static unsigned int seed;
 
 if ( init != 0 ){
  seed ^= init;
 }
 seed *= 52341;
 seed += 37;
 return (seed ^ 0x1234);
}

こんどのはどうでしょうか。
試して見て下さい。
※乗算そのものが重い処理になるならまた別タイプを載せます。

この回答への補足

質問者です。
動きました!
しばらく、使ってみて様子をみてみます。
ありがとうございました。

補足日時:2007/07/05 14:54
    • good
    • 0
この回答へのお礼

改良版、ありがとうございます。
見た感じ、軽そうですね。
明日、動かしてみます。
また結果、報告します。

お礼日時:2007/07/04 21:52

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!