Toggle Theme Editor
Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Charcoal

[TIP]Kỹ thuật random, tạo danh sách (mảng) ngẫu nhiên trong java

Discussion in 'Hướng dẫn người mới bắt đầu' started by JackV, 22/10/11.

  1. JackV

    JackV Administrator Staff Member

    Ở bài viết này JackV sẽ hướng dẫn các bạn 3 kỹ thuật random thường dùng:
    1. Random tự nhiên, có thể lặp lại.
    2. Random có thể lặp lại nhưng 2 phần tử liên tiếp không trùng nhau.
    3. Random không lặp lại.

    Các bạn có thể random các phần tử trong một danh sách theo cách này, ở đây mình sẽ làm trường hợp đơn giản nhất có thể ứng dụng cho những trường hợp random danh sách.

    Mình sẽ thực hiện random một dãy 10 số int, xem như random index của một danh sách khoảng 100 phần tử..

    Sau khi khởi tạo
    PHP:
            Random rd = new Random();
    1. Random tự nhiên, có thể lặp lại
    Bạn sẽ sử dụng rd.nextInt(100); trong trường hợp này thì các số cho kết quả sẽ nằm từ 0-99.

    2. Để random tự nhiên có thể lặp lại nhưng hai phần tử liền kề không trùng nhau.
    Đơn giản là ta dùng một biến tạm để lưu giá trị random lần trước, khi random ra một giá trị mới thì kiểm tra, nếu giá trị mới khác giá trị cũ thì sử dụng rồi biến tạm set giá trị bằng giá trị mới.

    3. Random không lặp lại.
    Trong trường hợp này sử dụng một Vector, ta sẽ ứng dụng phương thức kiểm tra có chứa object hay không của vector v.contains(iNew) kết quả false thì chúng ta add thêm vào, cuối cùng ta có vector chứa các số không trùng nhau.

    Demo
    PHP:
    import java.util.Random;
    import java.util.Vector;

    /**
     *
     * @author Thanh Nhan <JackV at congdongjava.com>
     */
    public class HowToRandom {

        
    /**
         * @param args the command line arguments
         */
        
    public static void main(String[] args) {
            
    Random rd = new Random();

            
    //random 10 number bettween 100
            
    System.out.println("random 10 number bettween 100");
            for (
    int i 010i++) {
                
    System.out.println("Item " + (i+1) + ":" rd.nextInt(100));
            }
           
            
    //random new item difference from previous random item
            
    int iNewNumber 0iPrevious = -1;
            for (
    int i 010; ) {
                
    iNewNumber rd.nextInt(100);
                if (
    iNewNumber != iPrevious){
                    
    i++;
                    
    iPrevious iNewNumber;
                    
    System.out.println("Item " + (i+1) + ":" iNewNumber);
                }
            }
           
            
    //random 10 unique number
            
    Vector v = new Vector();
            
    int iNew 0;
            for (
    int i 010;  ) {
                
    iNew rd.nextInt(100);
                if (!
    v.contains(iNew)){
                    
    i++;
                    
    v.add(iNew);
                    
    System.out.println("Item " + (i+1) + ":" iNew);
                }
            }
        }
    }
     
    Last edited: 10/11/17
  2. monday0rsunday

    monday0rsunday Active Member

    Ðề: [TIP]Kỹ thuật random

    Mình xin góp thêm mở rộng cho 2) (thu nhỏ từ 3) là: random , nhưng ít nhất sau 1 số lần mới cho phép có khả năng bị trùng.
    Code:
            Random rd = new Random();
            Vector v = new Vector();
            int maxNumberOccur = 3;
            int iNewNumber = 0;
            for (int i = 0; i < 10; i++) {
                do{
                    iNewNumber = rd.nextInt(100);
                }while(v.contains(iNewNumber));
                if(!v.isEmpty()&&v.size()>=maxNumberOccur) v.remove(0);
                v.add(iNewNumber);
                System.out.println("Item " + (i+1) + ":" + iNewNumber);
            }
    
     
  3. JackV

    JackV Administrator Staff Member

    Ðề: [TIP]Kỹ thuật random

    Sao bạn lại nói là bỏ tính trùng nhau đi xem như không random?

    Hãy chọn ngẫu nhiên 3 trong 5 người có mặt sớm nhất phỏng vấn lần 1.
    ngẫu nhiên > Random
    3 trong 5 người > Không trùng.
    >>> Chọn ngẫu nhiên nhưng không được chọn lại phần tử đã chọn. Vụ này dùng vector, cái nào chọn rồi thì remove sẽ đơn giản.
     
  4. monday0rsunday

    monday0rsunday Active Member

    Ðề: [TIP]Kỹ thuật random

    Sr. Mình sẽ đính chính lại. :D
     
  5. hongtamtk

    hongtamtk Member

    Ðề: [TIP]Kỹ thuật random

    Sao mình sử dụng hàm Random ko dc, mình thấy các bạn import java.util.Random;
    nhưng mình dùng netbeans ko có cái này nó vẫn bình thường và dùng rd.nextInt(100) ko dc hepl với.
     
  6. JackV

    JackV Administrator Staff Member

    Ðề: [TIP]Kỹ thuật random

    Bạn không post code thì không giúp được đâu bạn à.
     
  7. monday0rsunday

    monday0rsunday Active Member

    Ðề: [TIP]Kỹ thuật random

    Chuyện có lỗi mà IDE ko báo ko phải là chuyện ko thể xảy ra. Có lần tớ còn bị nó báo lỗi mà ko hiểu lỗi ở đâu (chỉ có mở lại mà có lỗi) =.=".
    Có thể jdk/jre của bạn có lỗi ko chứa gói java.util, hoặc gì gì đó:D
    Ps:
    có 2 cách gọi random, 1 là dùng java.util.Random, 2 là dùng java.lang.Math
    java.util.Random thì cho phép nhiều lựa chọn hơn (nguyên, thực, giữa 1 khoảng...)
    Còn Math thì chỉ có 1: giữa 0.0 và 1.0 (gọi method static Math.random()). Đơn giản bạn có thể dùng (int)(Math.random()*100) để thay thế, nếu ko xử lí đc lỗi.
     
  8. thuyloanoi

    thuyloanoi New Member

    Lần trước phỏng vấn có câu code Random này mà ko làm đc. Giờ thì hiểu rùi, thanks chủ topic nhé ^.^
     
  9. Gemini Tran

    Gemini Tran New Member

    Mình muốn mở rộng topic này ở khía cạnh: tạo random 1 phần tử sao cho không trùng lặp từ 1 thư viên phần tử, cho rằng thư viện này chứa số phần tử rất lớn (hàng triệu trở lên). Vậy hướng tiếp cận thế nào để tối ưu?
    VD: cần tạo 1 phần tử mới, có dạng thế này: aI82ZltwE sao cho phần tử mới tạo ra không được trùng với bất kỳ phần tử nào trong một tập hợp các phần tử đồng dạng với phần tử cần tạo. Mỗi phần tử có độ dài là 9, được tạo ra bằng cách random các ký tự (a-z, A-Z, 0-9).
     
  10. JackV

    JackV Administrator Staff Member

    Lấy ra hay là tạo ra vậy bạn, 2 cái khác nhau à nha. Ra đề như vậy không có ví dụ kèm theo thì có nhiều cách hiểu lắm đó bạn.
    Đề này có vấn đề lớn ẩn dấu trong nó đây, nếu tập hợp đó đã lớn rồi mà phần tử tạo ra có 9 ký tự không theo cấu trúc (ví dụ AABBCCDDE AA là số, BB là chữ, ...) nào cả thì phần kiểm tra sẽ rất là hao tốn xử lý, để kiểm tra có thể dùng database nhưng khi không có cấu trúc có thể sẽ phải random số lượng rất lớn mới tìm ra được phần tử không trùng với phần tử nào của thư viện.
     
  11. Gemini Tran

    Gemini Tran New Member

    @JackV: yêu cầu là tạo mới, anh :D
    Với bài toán này thì mình cần phải đưa ra giải pháp lưu trữ cũng như cấu trúc của phần tử để thực hiện tạo & truy xuất hiệu quả nữa :D
     
  12. Nancru

    Nancru CongDongJava Project Leader Staff Member

    cái đoạn random này giống của mediafire nhỉ. Thường thì để lấy một unique key thì mình thấy lấy thời gian hiện tại tính bằng nano giây băm ra hoặc mã hóa, như vậy ko cần quay lại db để check unique cũng đc
     
  13. JackV

    JackV Administrator Staff Member

    [TIP]Kỹ thuật random
    Đây là một bài hướng dẫn, bạn hiện thực vấn đề để mọi người mở rộng đi.
    Bạn có thể tạo một chủ đề mới [TIP]Kỹ thuật random nâng cao và hiện thực hướng dẫn của bạn cho mọi người trao đổi nhé.
     
    Tannd likes this.
  14. Nhoc con PTIT

    Nhoc con PTIT Member

    Sao mình sinh ngẫu nhiên từ 1->5 mà lại trùng là thế nào nhỉ
     
  15. JackV

    JackV Administrator Staff Member

    Bạn nêu vấn đề cần phải rõ ràng hơn. Nêu vấn đề không có code như vậy thì chỉ có thể đoán mò, bạn tự đoán đi.
     
  16. nhohb2011

    nhohb2011 Active Member

    Đóng góp thêm 1 kỹ thuật ramdom không trùng với mảng cho trước, dùng Collections.shuffle.

    Đầu tiên ta phải khởi tạo 1 danh sách:
    Code:
    java.util.List<Integer> arrayList = new ArrayList();
    Thêm 100 phần tử vào danh sách:
    Code:
    for(int i = 0; i < 100; i++){
            arrayList.add(i + 1);
    }
    Sau đó dùng Collections.shuffle để xáo trộn danh sách này, ta sẽ được 1 danh sách mới với các phần tử đã bị xáo trộn.


    Code:
    java.util.Collections.shuffle(arrayList);
    DEMO:
    Code:
    import java.util.ArrayList;
    import java.util.Arrays;
    
    /**
    * @author  : huynhnguyen.it@gmail.com
    * @project : AdsPoster
    * @document: Collections.java
    * @created : Sep 20, 2013 12:43:45 PM
    */
    public class Collections {
        public static void main(String[]a){
            java.util.List<Integer> arrayList = new ArrayList();
    
            for(int i = 0; i < 100; i++){
                arrayList.add(i + 1);
            }
    
            java.util.Collections.shuffle(arrayList);
    
            for(int i = 0; i < arrayList.size(); i++){
                System.out.print(arrayList.get(i) + " ");
            }
        }
    }
    
     
    Nhoc con PTIT and JackV like this.
  17. Nhoc con PTIT

    Nhoc con PTIT Member

    Code:
    public class NewClass {
        public static void main(String[] args) {
            int[] a=new int [5];
            Random ran=new Random();
            a[0]= ran.nextInt()%5+1;
            int b,j;
            for(int i=1;i<5;i++){
                Try:
                b=ran.nextInt()%5+1;
                for(j=i-1;j>=0;j--)
                      if(a[j]==b)  {GOTO Try;}
                a[i]=b;
            }
            for(int i=0;i<5;i++)
                System.out.println(a[i]+"  ");
        }
    }
    
    Đây bác ak
     
  18. SITUVN

    SITUVN Well-Known Member

    Bạn dùng goto được à? Mình dùng không được.
    Thử trên http://www.compileonline.com/compile_java_online.php thì nó chạy không được (JDK, JRE 1.7), mình phải sửa thành continue.
    goto trong java tuy là một từ khóa nhưng chưa có chức năng, thay vào đó có thể dùng break và continue thay cho nó. Trên StackOverflow cũng nói thế.

    Kết quả sau khi sửa:
    PHP:
    import java.util.Random;

    public class 
    NewClass {
        public static 
    void main(String[] args) {
            
    int[] = new int [5];
            
    Random ran = new Random();
            
    int b,j;
            
    Out:
            for(
    int i 05i++){
                
    Math.abs(ran.nextInt() % 5) + 1;
                
    System.out.println(": " b);
                for(
    0ij++) {
                      if(
    a[j] == b) {
                        
    i--;
                        continue 
    Out;
                      }
                }
                
    System.out.println(": " " OK!");
                
    a[i] = b;
            }
            
    System.out.println("Result: ");
            for(
    int i 05i++)
                
    System.out.print(a[i] + "  ");
        }
    }
    Kết quả ngẫu nhiên:
    Code:
    0: 3
    0: 3 OK!
    1: 1
    1: 1 OK!
    2: 1
    2: 4
    2: 4 OK!
    3: 3
    3: 5
    3: 5 OK!
    4: 4
    4: 2
    4: 2 OK!
    Result:
    3  1  4  5  2
    
     
  19. SITUVN

    SITUVN Well-Known Member

    Cách làm ngẫu nhiên của bạn thấy hay phết. Ngẫu nhiên từ 1 đến n, mà không số nào "đụng hàng" nhau :)). Giống như là xáo trộn vị trí.

    Sửa tí cho nó "cơ động" 1 tí:
    PHP:
    import java.util.Random;

    public class 
    NewClass {
        public static 
    int[] Shuffle(int n) {
            
    int[] = new int [n];
            
    Random ran = new Random();
            
    int i 0jb;
            
    boolean isDuplicated false;
          while (
    a.length) {
                
    // Dùng Math.abs() để tráng số âm và 0
                
    Math.abs(ran.nextInt() % a.length) + 1;
                
    System.out.println("Index: " ", Number: " b);
                
    isDuplicated false;
                
    // Có thể tách thành 1 phương thức riêng
                
    for(0ij++) {
                      if(
    a[j] == b) {
                        
    isDuplicated true;
                      }
                }
                
    // Nếu không trùng thì gán và tăng i
                
    if (!isDuplicated) {
                    
    System.out.println("OK!");
                    
    a[i] = b;
                    
    i++;
                }
                
    // Nếu trùng thì tếp tục "dò số"
            
    }
            
    System.out.println("\r\nResult: ");
            for(
    0a.lengthi++) {
                
    System.out.print(a[i] + "  ");
            }
            return 
    a;
        }
        public static 
    void main(String[] args) {
            
    Shuffle(20);
        }
    }
    Kết quả ngẫu nhiên:
    Code:
    Index: 0, Number: 15
    OK!
    Index: 1, Number: 20
    OK!
    Index: 2, Number: 18
    OK!
    Index: 3, Number: 12
    OK!
    Index: 4, Number: 5
    OK!
    Index: 5, Number: 20
    Index: 5, Number: 16
    OK!
    Index: 6, Number: 15
    Index: 6, Number: 17
    OK!
    Index: 7, Number: 12
    Index: 7, Number: 10
    OK!
    Index: 8, Number: 17
    Index: 8, Number: 12
    Index: 8, Number: 8
    OK!
    Index: 9, Number: 12
    Index: 9, Number: 15
    Index: 9, Number: 3
    OK!
    Index: 10, Number: 9
    OK!
    Index: 11, Number: 19
    OK!
    Index: 12, Number: 11
    OK!
    Index: 13, Number: 2
    OK!
    Index: 14, Number: 9
    Index: 14, Number: 3
    Index: 14, Number: 12
    Index: 14, Number: 12
    Index: 14, Number: 7
    OK!
    Index: 15, Number: 18
    Index: 15, Number: 2
    Index: 15, Number: 4
    OK!
    Index: 16, Number: 8
    Index: 16, Number: 13
    OK!
    Index: 17, Number: 12
    Index: 17, Number: 2
    Index: 17, Number: 5
    Index: 17, Number: 20
    Index: 17, Number: 9
    Index: 17, Number: 16
    Index: 17, Number: 20
    Index: 17, Number: 10
    Index: 17, Number: 14
    OK!
    Index: 18, Number: 20
    Index: 18, Number: 15
    Index: 18, Number: 11
    Index: 18, Number: 19
    Index: 18, Number: 13
    Index: 18, Number: 14
    Index: 18, Number: 17
    Index: 18, Number: 16
    Index: 18, Number: 9
    Index: 18, Number: 5
    Index: 18, Number: 2
    Index: 18, Number: 18
    Index: 18, Number: 11
    Index: 18, Number: 12
    Index: 18, Number: 1
    OK!
    Index: 19, Number: 12
    Index: 19, Number: 9
    Index: 19, Number: 18
    Index: 19, Number: 18
    Index: 19, Number: 7
    Index: 19, Number: 13
    Index: 19, Number: 15
    Index: 19, Number: 20
    Index: 19, Number: 12
    Index: 19, Number: 9
    Index: 19, Number: 14
    Index: 19, Number: 12
    Index: 19, Number: 18
    Index: 19, Number: 6
    OK!
    
    Result:
    15  20  18  12  5  16  17  10  8  3  9  19  11  2  7  4  13  14  1  6
    
    Càng về cuối và số lượng càng nhiều thì càng lâu. Nên cách này chưa hiệu quả nhất

    Mới hồi hôm viết một bài về chọn ngẫu nhiên theo phần trăm bên http://CongDongCViet.com giờ lại ngẫu nhiên bên này, đoạn mã ngẫu nhiên thấy na ná nhau =)).

    Cơn bản là rảnh:
    PHP:
    import java.util.Random;
    import java.security.InvalidParameterException;

    public class 
    RandomTest {

        public static 
    int[] Shuffle(int beginint endthrows InvalidParameterException {
            return 
    Shuffle(beginendend begin 1);
        }

        public static 
    int[] Shuffle(int beginint endint shuffleTimesthrows InvalidParameterException {
            if (
    end begin <= || shuffleTimes 1) throw new InvalidParameterException("Numer of element and shuffle times must larger than 1!");
            
    int[] = new int[end begin 1];
            
    int ijabt;
            
    Random ran = new Random();
            for (
    0beginr.lengthi++, j++) {
                
    r[i] = j;
            }
            
    //
            
    for (0shuffleTimesi++) {
                
    Math.abs(ran.nextInt(r.length));
                
    Math.abs(ran.nextInt(r.length));
                if (
    != b) {
                    
    r[a];
                    
    r[a] = r[b];
                    
    r[b] = t;
                }
            }
            return 
    r;
        }
        public static 
    void main(String[] args) {
            if (
    args.length 1) {
                try {
                    
    int[] result;
                    if (
    args.length == 2)
                    
    result Shuffle(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
                    else
                    
    result Shuffle(Integer.parseInt(args[0]), Integer.parseInt(args[1]), Integer.parseInt(args[2]));
                    for (
    int i 0result.lengthi++) {
                       
    System.out.print(result[i] + " ");
                    }
                    
    System.out.println("\r\n" result.length);
                } catch(
    InvalidParameterException ex) {
                    
    System.out.println(ex.getMessage());
                } catch (
    Exception ex) {
                    
    System.out.println("An error has occured: " ex.getMessage());
                }
            } else {
                
    System.out.println("Usage: RandomTest BeginNumber EndNumber [ShuffleTime]");
            }
        }
    }
     
  20. Joe

    Joe Thành viên VIP

    =)) By the way, I got an idea:
    PHP:
            HashMap hm = new HashMap();
            for(
    int i 05i++){
                
    Math.abs(ran.nextInt() % 5) + 1;
                
    System.out.println(": " b);
                if (
    hm.put(b+""b) == null) {
                    
    System.out.println(": " " OK!");
                    
    a[i] = b;
                } else --
    i;
    It does not look "sophisticated" but it requires neither the 2nd loop nor the GOTO/continue.
     
  21. Lara Croft

    Lara Croft New Member

    Thế làm thế nào để random trong khoảng [a, b] ạ? (a, b là các số nguyên)
     

Chia sẻ trang này

Loading...