java生成抽樣隨機數的多種算法。本站提示廣大學習愛好者:(java生成抽樣隨機數的多種算法)文章只能為提供參考,不一定能成為您想要的結果。以下是java生成抽樣隨機數的多種算法正文
本章先講授Java隨機數的幾種發生方法,然後經由過程示例對其停止演示。
概述:
這裡你是否是會說,生成隨機數有甚麼難的?不就是直接應用Java封裝好了的random就好了麼?固然關於普通情形下是OK的,並且本文要解釋的這些算法也是基於這個random庫函數的。
本文重要是針對抽樣這一行動停止的,而抽樣自己有一個隱含的規矩就是不要有反復數據。好了,有了這些解釋。你可以先測驗考試著用一些本身的設法主意來完成不反復地生成隨機數。
算法測驗考試:
一些好的算法湧現,常常隨同著一些不那末好的算法。然則關於後果不太好的算法,它們廣泛有一個個性,便利懂得和完成。上面是經由過程一個按部就班的方法來作一個簡略地解釋。
第一次測驗考試:樸實隨機算法
這個算法很好懂得,就是隨機!每次發生一個隨機數,並參加聚集。
private void simpleRandom(int start, int end, int count) {
System.out.println("樸實隨機算法:");
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < count; i++) {
int random = NumberUtils.randomInteger(start, end);
buffer.append(i == 0 ? ("[" + random) : (", " + random));
}
buffer.append("]");
System.out.println(buffer);
}
第二次測驗考試:檢討存在性隨機算法
我們曉得下面的辦法有一個成績,就是能夠會有反復數據。因而,我們就想到,在生成一個隨機數的時刻停止檢討一下這個數是否是曾經存在了,假如存在了就從新生成。
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--;
continue;
}
save.add(random);
buffer.append(i == 0 ? ("[" + random) : (", " + random));
}
buffer.append("]");
System.out.println(buffer);
}
第三次測驗考試:元素移除隨機算法
下面的算法曾經處理了數據反復的成績。不外,有一個很蹩腳的成績就是能夠我們要消費很長的時光來生成抽樣隨機數(這個要看臉了。。。。)。
不外,這裡我們有了新設法主意。那就是在一個聚集中去隨機一個數,當這個被選中的時刻就remove失落,那末下次再隨機的時刻是否是就不會再隨機到這個數了?如許就很好地處理了隨機數的反復成績。代碼以下:
private void removeRandom(int start, int end, int count) {
System.out.println("元素移除隨機算法:");
StringBuffer buffer = new StringBuffer();
List<Integer> numbers = initList(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(random);
}
buffer.append("]");
System.out.println(buffer);
}
第四次測驗考試:狀況轉移隨機算法
在我之前的許多博客中,就有一些是算法中的狀況轉移進程。而狀況的轉移也是我最愛好的算法之一。上面的圖-1中標注了隨機數的取值規模,序列中的橙色數字是成果中的隨機序列。最下方的序列中有一些虛線的箭頭,代表了狀況的轉移。
圖-1 基於狀況轉移的抽樣隨機數生成算法
完成代碼:
private void statusRandom(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(random);
if (status[random] == 0) {
buffer.append(i == 0 ? ("[" + random) : (", " + random));
status[random] = random == end ? start : (random + 1); // 弗成能有在start之前的數字
} else {
// 狀況轉移
int index = random;
do {
index = status[index];
} while (status[index] != 0);
buffer.append(i == 0 ? ("[" + index) : (", " + index));
status[index] = index == end ? start : (index + 1); // 弗成能有在start之前的數字
}
}
buffer.append("]");
System.out.println(buffer);
}
第五次測驗考試:遞歸Floyd隨機算法
Floyd算法說究竟也是一種狀況的轉移進程。該算法會請求輸出一個List或是array來保留曾經肯定的隨機數。望文生義,這裡我會用到遞歸的解法。在遞歸的進程中,我們把第i個隨機數的狀況轉移到了第i-1個隨機身上了。代碼以下:
private List<Integer> simpleFloyd(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);
}
return list;
}
第六次測驗考試:迭代Floyd隨機算法
思緒與下面的遞歸Floyd隨機算法是類似的,不外,這裡我們參加了一個變量來做優化。就不須要再去遞歸了。代碼以下:
private List<Integer> iterationFloyd(int start, int end, int count) {
System.out.println("迭代Floyd隨機算法:");
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 隨機數生成算法測試成果
在下面的測試成果中,我們可以很顯著地看出樸實隨機算法不只有反復數據,並且照樣最耗時的。所以,在抽樣的隨機數生成時,防止應用這一算法。而在後幾種算法中,狀況轉移隨機算法最好,迭代Floyd隨機算法次之。這個可以依據小我偏心來做選擇。