一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - java生成抽樣隨機數的多種算法

java生成抽樣隨機數的多種算法

2020-06-26 16:01Q-WHai JAVA教程

本文主要介紹了java生成抽樣隨機數的多種算法,主要是基于random庫函數的,有需要的可以了解一下。

本章先講解Java隨機數的幾種產生方式,然后通過示例對其進行演示。

概述:

這里你是不是會說,生成隨機數有什么難的?不就是直接使用Java封裝好了的random就行了么?當然對于一般情況下是OK的,而且本文要說明的這些算法也是基于這個random庫函數的。

本文主要是針對抽樣這一行為進行的,而抽樣本身有一個隱含的規則就是不要有重復數據。好了,有了這些說明。你可以先嘗試著用一些自己的想法來實現不重復地生成隨機數。

算法嘗試:

一些好的算法出現,往往伴隨著一些不那么好的算法。但是對于效果不太好的算法,它們普遍有一個共性,方便理解和實現。下面是通過一個循序漸進的方式來作一個簡單地說明。

第一次嘗試:樸素隨機算法

這個算法很好理解,就是隨機!每一次產生一個隨機數,并加入集合。 

?
1
2
3
4
5
6
7
8
9
10
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);
 }

第二次嘗試:檢查存在性隨機算法

我們知道上面的方法有一個問題,就是可能會有重復數據。于是,我們就想到,在生成一個隨機數的時候進行檢查一下這個數是不是已經存在了,如果存在了就重新生成。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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掉,那么下次再隨機的時候是不是就不會再隨機到這個數了?這樣就很好地解決了隨機數的重復問題。代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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中標注了隨機數的取值范圍,序列中的橙色數字是結果中的隨機序列。最下方的序列中有一些虛線的箭頭,代表了狀態的轉移。

java生成抽樣隨機數的多種算法

圖-1 基于狀態轉移的抽樣隨機數生成算法

實現代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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個隨機身上了。代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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隨機算法是相似的,不過,這里我們加入了一個變量來做優化。就不需要再去遞歸了。代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
  }

測試結果:

java生成抽樣隨機數的多種算法

圖-2 隨機數生成算法測試結果

在上面的測試結果中,我們可以很明顯地看出樸素隨機算法不僅有重復數據,而且還是最耗時的。所以,在抽樣的隨機數生成時,避免使用這一算法。而在后幾種算法中,狀態轉移隨機算法最佳,迭代Floyd隨機算法次之。這個可以根據個人偏愛來做選擇。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美精品一区视频 | 啊啊啊好爽在线观看 | 成人国产一区 | 国产一区二区三区欧美精品 | 日韩精品一区二区三区老鸭窝 | www.av免费| 国产精品suv一区二区 | 国产综合第一页 | 日本中文字幕一区二区高清在线 | 国产成人8x视频一区二区 | 香蕉tv亚洲专区在线观看 | 免费超级乱淫视频播放性 | 男女真实无遮挡xx00动态图软件 | 亚洲国产欧美另类 | 俄罗斯一级淫片 | 明星乱淫 | 国产成人亚洲精品一区二区在线看 | 国产资源免费 | 9色视频在线观看 | 嫩草视频在线观看免费 | 天堂俺去俺来也www久久婷婷 | 国产精品成人免费福利 | 91sao国产在线观看 | 欧美3d怪物交videos网站 | 忘忧草高清 | 国产精品青青在线观看香蕉 | 91久久国产露脸精品 | 成人软件18免费 | 禁忌4中文 | 精品久久久久久无码人妻国产馆 | 国产目拍亚洲精品一区二区三区 | 91高清国产经典在线观看 | 国产久热香蕉在线观看 | 日本免费在线播放 | 边吃胸边膜下刺激免费男对女 | 国产精品久久久久久久久齐齐 | 欧美综合一区二区三区 | 久久99热成人精品国产 | 国产伦精品一区二区三区免 | 欧美在线视频一区 | 国产成人精品免费午夜 |