この章では、最初にJava乱数を生成するいくつかの方法を説明し、その後、例を介してそれらを実証します。
概要:
ここで、乱数を生成することの難しさは何ですか? Javaカプセル化されたランダムを使用するだけではありませんか?もちろん、一般的には問題ありません。この記事で説明するアルゴリズムは、このランダムライブラリ機能にも基づいています。
この記事では、主にサンプリングの動作に焦点を当てており、サンプリング自体には、データを重複させない暗黙のルールがあります。わかりました、これらの指示があります。最初に、独自のアイデアのいくつかを使用して、繰り返し発生せずに乱数を生成することができます。
アルゴリズムの試み:
いくつかの優れたアルゴリズムが表示され、多くの場合、それほど良くないアルゴリズムを伴います。ただし、あまり効果的ではないアルゴリズムの場合、一般的に1つの共通の機能があり、理解して実装しやすいです。以下は、段階的なアプローチを介した簡単な説明です。
最初に試してください:ナイーブランダムアルゴリズム
このアルゴリズムは理解しやすく、ランダムです!乱数が生成されるたびにセットに追加されます。
private void simplerandom(int start、int end、int count){system.out.println( "Natural Random Algorithm:"); stringbuffer buffer = new StringBuffer(); for(int i = 0; i <count; i ++){int random = numberutils.randominteger(start、end); buffer.append(i == 0?( "[" +ランダム):( "、" +ランダム)); } buffer.append( "]"); System.out.println(バッファー); } 2番目の試み:実存的なランダムアルゴリズムを確認します
上記の方法に問題があること、つまり、データが重複する可能性があることを知っています。したがって、乱数を生成するときに数値が既に存在するかどうか、それが存在する場合、それが再生されるかどうかを確認することを考えました。
private void checkRandom(int start、int end、int count){system.out.println( "実存ランダムアルゴリズムを確認:"); stringbuffer buffer = new StringBuffer(); List <Integer> save = new ArrayList <>(); for(int i = 0; i <count; i ++){int random = numberutils.randominteger(start、end); if(exits(save、random)){i--;続く; } save.add(random); buffer.append(i == 0?( "[" +ランダム):( "、" +ランダム)); } buffer.append( "]"); System.out.println(バッファー); } 3番目の試み:要素削除ランダムアルゴリズム
上記のアルゴリズムは、データの複製の問題を解決しました。ただし、非常に悪い問題の1つは、サンプル乱数を生成するのに長い時間がかかる可能性があることです(これは顔に依存します...)。
ただし、ここには新しいアイデアがあります。つまり、セットで数値をランダムに使用し、選択したときに削除することです。それでは、ランダムな場合、この数値に再びランダムに到達しませんか?これにより、乱数の繰り返しの問題が非常によく解決されます。コードは次のとおりです。
private void removerandom(int start、int end、int count){system.out.println( "要素削除ランダムアルゴリズム:"); stringbuffer buffer = new StringBuffer(); List <Integer> numbers = initglist(start、end); for(int i = 0; i <count; i ++){int random = numberutils.randominteger(count -i); buffer.append(i == 0?( "[" + numbers.get(random)):( "、" + numbers.get(random))); numbers.Remove(ランダム); } buffer.append( "]"); System.out.println(バッファー); } 4番目の試み:状態転送ランダムアルゴリズム
私の以前のブログの多くでは、一部はアルゴリズムの状態転送プロセスです。状態転送も私のお気に入りのアルゴリズムの1つです。以下の図1は、乱数の値範囲を示し、シーケンスのオレンジ色の数は結果のランダムシーケンスです。底部のシーケンスには、状態の移行を表すいくつかの点線の矢印があります。
図1状態遷移に基づく乱数生成アルゴリズム
実装コード:
private void statesrandom(int start、int end、int count){system.out.println( "ステータス転送ランダムアルゴリズム:"); stringbuffer buffer = new StringBuffer(); int [] status = new int [end + 1]; for(int i = 0; i <count; i ++){int random = numberutils.randominteger(start、end); system.err.println(ランダム); if(status [random] == 0){buffer.append(i == 0?( "[" + random):( "、" + random));ステータス[ランダム] =ランダム== end?開始:(ランダム + 1); //開始前に数字を持つことは不可能です} else {//ステータス転送int index = random; {index = status [index]; } while(status [index]!= 0); buffer.append(i == 0?( "[" + index):( "、" + index));ステータス[index] = index == end?開始:(インデックス + 1); //開始前に番号を持つことは不可能です}} buffer.append( "]"); System.out.println(バッファー); } 5回目の試み:再帰フロイドランダムアルゴリズム
フロイドアルゴリズムは、最終的には状態転送プロセスです。アルゴリズムでは、決定された乱数を保存するためにリストまたは配列が必要です。名前が示すように、ここで再帰ソリューションを使用します。再帰の過程で、I番目の乱数の状態をI-1乱数に転送します。コードは次のとおりです。
プライベートリスト<integer> simpleflyd(list <integer> list、int count、int start、int end){if(count == 0){return list; } list = simplefloyd(list、count -1、start、end -1); int random = numberutils.randominteger(start、end); if(list.contains(random)){list.add(end); } else {list.add(random); }返品リスト。 } 6回目の試み:フロイドランダムアルゴリズムを繰り返します
このアイデアは、上記の再帰フロイドランダムアルゴリズムに似ていますが、ここでは最適化する変数を追加します。もう繰り返す必要はありません。コードは次のとおりです。
プライベートリスト<integer> iterationflyd(int start、int end、int count){system.out.println( "iterative floyd random algorithm:"); List <Integer> list = new ArrayList <>(); for(int i = end -count+1; i <end; i ++){int random = numberutils.randominteger(start、i); if(list.contains(random)){list.add(i); } else {list.add(random); }} return list; }テスト結果:
図2乱数生成アルゴリズムテスト結果
上記のテスト結果では、素朴なランダムアルゴリズムには複製データがあるだけでなく、最も時間がかかることも明確にわかります。したがって、サンプリングされた乱数を生成するときにこのアルゴリズムを使用しないでください。後者のアルゴリズムの中で、状態転送ランダムアルゴリズムが最適であり、反復フロイドランダムアルゴリズムが2番目です。これは、個人的な好みに従って行うことができます。