2011-01-31 34 views
10

thể Duplicates:
c# - getting the same random number repeatedly
Random number generator not working the way I had planned (C#)Random Number Generation - Cùng Số trở

Tôi có một phương pháp mà xây dựng một danh sách các ints:

public Queue<int> generateTrainingInts(int count = 60) 
    { 
     Queue<int> retval = new Queue<int>(); 

     for (int i = 0; i < count; i++) 
     { 
      retval.Enqueue(JE_Rand.rInt(2001, 100)); 
     } 

     return retval; 
    } 

JE_Rand .rInt() chỉ là một hàm đại biểu es đến một chức năng của lớp Random:

public static int rInt(int exclUB, int incLB = 0) 
    { 
     Random rand = new Random(DateTime.Now.Millisecond); 
     int t = rand.Next(incLB, exclUB); 
     rand = null;    
     return t; 
    } 

Nhưng khi tôi gọi generateTrainingInts, cùng một số được enqueued mỗi lần. Tuy nhiên, nếu tôi thay đổi rInt để sử dụng một thể hiện tĩnh của lớp Random, thay vì một cá thể cục bộ (với phạm vi hàm như được định nghĩa ở trên), thì nó hoạt động chính xác (enqueue random integer). Có ai biết tại sao điều này xảy ra không?

Chỉnh sửa: Kính gửi những người trả lời không đọc kỹ câu hỏi của tôi, Giống như một số bạn đã chỉ ra, tôi đang tìm kiếm giải thích tốt về lý do điều này xảy ra. Tôi không tìm kiếm giải pháp cho cùng một vấn đề được tạo ra bằng số, bởi vì tôi đã sửa lỗi đó như tôi đã nói ở trên. Cảm ơn sự nhiệt tình của bạn mặc dù :) Tôi thực sự chỉ muốn hiểu những điều như thế này, bởi vì thực hiện đầu tiên của tôi có ý nghĩa hơn về khái niệm với tôi.

+0

vẻ trùng lặp ... Nhìn vào câu hỏi realted như -http: //stackoverflow.com/questions/1437825/random-number-generation-in-c –

+0

Nó xảy ra bởi vì các 'đối tượng Random' được khởi tạo từ 'Môi trường.GetTickCount', đó là một bộ đếm thời gian mili giây. Vì vậy, nếu bạn gọi hàm tạo 'Random' hai lần trong cùng một mili giây, bạn sẽ nhận được cùng một giá trị ban đầu. –

+0

Khi rand được khởi tạo với cùng một hạt giống (ví dụ: DateTime.Now.Millisecond trong trường hợp của bạn), nó sẽ trả về cùng một chuỗi các giá trị. Bạn nên khởi tạo nó một lần (và lưu trữ nó trong một biến tĩnh), hoặc với các hạt giống khác nhau tại mỗi thời điểm. – AFract

Trả lời

23

Bạn cần giữ cùng một đối tượng Random. Đặt nó bên ngoài phương pháp tĩnh của bạn là một thành viên tĩnh

private static Random rand = new Random(); 

public static int rInt(int exclUB, int incLB = 0) 
{ 
    int t = rand.Next(incLB, exclUB); 
    return t; 
} 

Sửa
Lý do là độ phân giải hữu hạn của đồng hồ sử dụng để khởi Random. Các khởi tạo tiếp theo của Random sẽ có cùng vị trí bắt đầu trong chuỗi ngẫu nhiên. Khi sử dụng lại cùng một Random, giá trị tiếp theo trong chuỗi ngẫu nhiên luôn được tạo ra.

+0

OP đã cố gắng và đã hỏi * tại sao *. –

+0

Tại sao chỉ định rand để null sau khi thế hệ ?? Như rand sẽ được khởi tạo trong một khoảng thời gian rất ngắn, cả hai trường hợp sẽ nhận được cùng một hạt giống và trả lại cùng một giá trị, chính xác như trong phiên bản của tác giả. Bạn nên đặt nó tĩnh và giữ cho cùng một ví dụ. Cũng có thể sử dụng nhiều cá thể với các hạt giống khác nhau, ví dụ bằng cách sử dụng "Guid.NewGuid(). GetHashCode()" làm hạt giống, nhưng bạn sẽ có được những màn trình diễn khủng khiếp. – AFract

+0

Tôi thấy bạn đã sửa mẫu mã của mình. Nó đã được boggus nhưng nó phải làm việc bây giờ ... – AFract

5

Hãy thử đoạn mã sau và tôi nghĩ rằng bạn sẽ thấy lý do tại sao:

void PrintNowAHundredTimes() 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     Console.WriteLine(DateTime.Now); 
    } 
} 

Các Random đối tượng đang nhận được hạt giống hơn và hơn. Điều này là do độ chi tiết của thời gian hệ thống được trả về bởi DateTime.Now, khá đơn giản, hữu hạn. Ví dụ, trên máy của tôi, giá trị chỉ thay đổi sau mỗi ~ 15 ms. Vì vậy, các cuộc gọi liên tiếp trong khoảng thời gian đó trở lại cùng một thời điểm.

Và như tôi nghi ngờ bạn đã biết, hai đối tượng được khởi tạo với cùng giá trị giống sẽ tạo ra các chuỗi ngẫu nhiên giống hệt nhau. (Đó là lý do tại sao nó được gọi là giả ngẫu, về mặt kỹ thuật.)

Bạn cũng nên lưu ý rằng ngay cả khi nó làm cho tinh thần để tạo một đối tượng mới Random địa phương trong phương pháp của bạn, thiết lập nó để null vẫn sẽ phục vụ không có mục đích (khi thoát khỏi phương thức sẽ không còn tham chiếu đến đối tượng nữa, vì vậy nó sẽ bị thu gom rác bất kể).

1
public class JE_Rand 
{ 
    private static Random rand= new Random(DateTime.Now.Millisecond); 

    public static int rInt(int exclUB, int incLB = 0) 
    { 
     int t = rand.Next(incLB, exclUB); 
     return t; 
    } 
} 
+0

lý do rand = null? nó sẽ đổ đối tượng, và cuộc gọi tiếp theo sẽ ném một ngoại lệ – walter

+0

@walter: Đây là một câu trả lời cũ, nhưng tôi đã chỉ sao chép và dán mã của mình và di chuyển ngẫu nhiên mới (....) bên ngoài của cuộc gọi phương thức. Bạn là 100% ngay mặc dù. Tôi sẽ chỉnh sửa câu trả lời của mình. – BFree