ハードウェア乱数生成器による乱数を得るには、
/dev/urandom
もしくは
/dev/random
を使う。/dev/urandomはハードウェア乱数生成器の乱数生成が間に合わない場合、疑似乱数を使うので/dev/randomの方が、より真の乱数に近いが、乱数生成が完了するまでプログラムがストップする。その為、/dev/urandomの方が使い勝手は良い。
なお、Ivy Bridge以降のCPUではCPUに独自のハードウェア乱数生成器が搭載されており、/dev/randomでも高速に乱数を生成することができる。
乱数の読み込みに必要な関数はopen()、read()、close()であり、ヘッダーはfcntl.hおよびunistd.hが必要となる。
/dev/randomおよび/dev/urandomから配列に読み込むことによって、一気に複数の乱数を得ることもできる。
実際のCコードであるが、まず下記のコードを実行してみる。
#include <iostream> #include <fcntl.h> #include <unistd.h> using namespace std; int main(void) { int fid=open("/dev/random", O_RDONLY); if (fid == -1) { cerr<<("can't open"); return fid; } long long int r[100]; for (int i=0;i<100;i++)r[i]=0; int ret=read(fid, &r, sizeof (r)); if (ret < 0) { cerr<<("can't read"); return ret; } cout<<"ret="<<ret<<" ret/size()= "<<ret/sizeof(long long int)<<endl; for (int i=0;i<100;i++) cout<<i<<" "<<r[i]<<endl; if (close(fid))cerr<<"can't close"; return 0; }
すると、
ret=84 ret/size()= 10 0 -6718051102082338824 1 5097410379476334973 2 -7809465558258835484 3 -7506695009096760579 4 1043311878644120306 5 2570282861251990761 6 9005240483906281924 7 -934377726622283194 8 8238844123701322014 9 8269152880138797499 10 3534958681 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0
のような結果が得られるはずである。この場合、84ビット分の乱数が得られ、long long intは8ビット使うので、10個分のみ正しく、最後の11個目は4ビット分しか埋まっていない不正な乱数である。
この場合、最初の10個だけを使えばよいが、
ret=6 ret/size()= 0 0 19155406562275
このような結果になった場合、最初の乱数も不正な乱数である。そのため、
配列を使わない通常の変数に乱数を読み込む場合、単純に
#include <iostream> #include <fcntl.h> #include <unistd.h> using namespace std; int main(void) { int fid=open("/dev/random", O_RDONLY); if (fid == -1) { cerr<<("can't open"); return fid; } long long int r=0; int ret=read(fid, &r, sizeof (r)); if (ret < 0) { cerr<<("can't read"); return ret; } cout<<"ret="<<ret<<" ret/size()= "<<ret/sizeof(long long int)<<endl; cout<<r<<endl; if (close(fid))cerr<<"can't close"; return 0; }
とすると、
ret=6 ret/size()= 0 204688894798701
となって、正しい乱数を得られない。たとえ6バイトでも乱数であるので、一見乱数を次々と生成しているように見えるが、平均値などをとると、乱数としては不適格な数値を出力している。
下記のようにコードを書いてやると、正しい乱数を得ることができる。
getrandomを使ってもハードウェア乱数を得ることができる。
必要なヘッダーは#include <linux/random.h>である。
最終更新日