Javaの乱数の方法と原則
乱数に関連する情報を確認し、特別に整理します
まず、Javaで乱数を生成するいくつかの方法について話しましょう
en。 。 。実際、上記の3番目の方法は、ランダムのデフォルト構造方法で乱数を生成するために使用されます。
方法2でランダムなクラスを構築するには、種子のないランダムクラスを構築する方法は2つあります。
種子なし:この方法は乱数を返し、各実行の結果は異なります。これはSystem.currenttimemillis()をシードとして使用するのと同等です。
種子の場合:このように、プログラムが何回実行されても、戻り結果は同じになります。 2つのランダムインスタンスが同じシードで作成されている場合、各インスタンスに同じメソッド呼び出しシーケンスが作成され、同じ数字のシーケンスを生成して返すことができます。
擬似ランダム番号
コンピューターの乱数は擬似ランダム数です
これがこのようなCプログラムです:
// rand_1.cpp#include <stdlib.h> static unsigned int rand_seed; unsigned int random(void){rand_seed =(rand_seed*123+59)%65536; return(rand_seed);} void random_start(void){int temp [2]; movemata(0x0040,0x006c、fp_seg(temp)、fp_off(temp)、4); rand_seed = temp [0];} void main(){unsigned int i、n; random_start(); for(i = 0; i <10; i ++)printf( "#u/t"、random()); printf( "/n");}乱数生成のプロセスを完全に説明しています。
初め、
movemata(0x0040,0x006c、fp_seg(temp)、fp_off(temp)、4);
この関数は、メモリデータの移動に使用されます。 FP_SEG(FAR POINTER TO SEGANG)は、TEMPアレイのセグメントアドレスを取得する関数であり、FP_OFF(Offsetへの遠いポインター)はTEMPアレイの相対アドレスを取得する関数であり、Moveata関数は、0040:006CHストレージユニットに配置された2つのメモリユニットに配置された2つのメモリユニットに配置されます。このようにして、0040:006CHの16ビット番号は、TEMPアレイを介してRAND_SEEDに送信できます。
2番、
rand_seed =(rand_seed*123+59)%65536;
これは、乱数を計算するために使用される方法です。乱数の計算方法は、同じコンピューターにインストールされている異なるオペレーティングシステムでさえ、異なるコンピューターで異なります。それぞれLinuxとWindowsで試しました。これら2つのオペレーティングシステムで同じランダムシードによって生成される乱数は異なります。つまり、計算方法が異なることを意味します。
それから、
movemata(0x0040,0x006c、fp_seg(temp)、fp_off(temp)、4);
なぜランダムシードをメモリの0040:006CHで取得する必要があるのですか? 0040:006CHに何が保管されていますか?
「コンピューターコンポーネントとインターフェイステクノロジーの原則」というコースを研究した人は、ROM BIOSクロック割り込みサービスプログラムをコンパイルするとき、Intel 8253タイミング/カウンターが使用されることを覚えている場合があります。 Intel 8259割り込みチップとの通信により、割り込みサービスプログラムが操作できます。マザーボードによって生成された18.2の割り込みは、プロセッサによって生成されます。プロセッサは、タイミング/カウンター値に基づいて割り込みチップを制御します。現在のシステム時間を計算するために、コンピューターのマザーボードにそのようなタイミング/カウンターがあります。クロック信号サイクルが通過するたびにカウンターが追加されます。このカウンターの価値はどこに保存されますか?そうです、ちょうど0040:006CHメモリで、このメモリスペースは実際にこのように定義されています。
Timer_low DW?;アドレスは0040:006CHです
Timer_high DW?;アドレスは0040:006EHです
Timer_oft db? ;アドレスは0040:0070Hです
クロック割り込みサービスプログラムでは、Timer_lowがいっぱいになると、カウンターもいっぱいになり、カウンターの値がゼロになります。つまり、Timer_lowの16ビットバイナリがゼロになり、Timer_Highが追加されます。 rand01.c
movemata(0x0040,0x006c、fp_seg(temp)、fp_off(temp)、4);
まさに、2つの16ビットバイナリ番号TIMER_LOWとTIMER_HIGHがTEMPアレイに配置され、RAND_SEEDに送信され、「ランダムシード」が得られます。
さて、決定できることの1つは、ランダムシードがシステムクロックから、またはコンピューターマザーボードのタイミング/カウンターからメモリの記録値から得られることです。
en ...最後はありません。 。 LVL--
別のコードを見てみましょう:
//rand_2.cpp#include <iostream> #include <cstdlib> sutspace std; int main(){srand((unsigned)time(null)); unsigned int r = rand(); cout << "r =" << r << endl; // C ++ 98標準によれば、メイン関数は、戻りステートメントを使用して0;}を使用せずに導入できます;}ここで、ユーザーと他のプログラムがランダムシードを設定しない場合、システムタイミング/カウンターの値はランダムシードとして使用されます。したがって、同じプラットフォーム環境では、exeをコンパイルして生成した後、実行するたびに表示される乱数は擬似ランダム数になります。つまり、実行するたびに表示される結果は異なります。
要約します
乱数は、特定の計算方法に基づいてランダムシードによって計算される値です。したがって、計算方法が確実であり、ランダムシードが確実である限り、生成される乱数は変わりません。同じプラットフォーム環境では、exeをコンパイルして生成した後、表示される乱数は実行するたびに同じです。これは、同じコンピレーションプラットフォーム環境では、ランダムシードから乱数を生成するための計算方法が同じであり、ランダムシードが同じであるため、生成される乱数は同じであるためです。
ユーザーまたはサードパーティがランダムシードを設定しない限り、デフォルトではランダムシードはシステムクロック(つまり、タイミング/カウンターの値)から生まれます。
読んでくれてありがとう、私はそれがあなたを助けることができることを願っています。このサイトへのご支援ありがとうございます!