2011-08-13 36 views
5

Tôi cố gắng để sử dụng F # để tạo ra một danh sách các TripleS ngẫu nhiên -> hai số ngẫu nhiên và tổng của chúng:thế hệ ngẫu nhiên vào danh sách fsharp

let foo minNum maxNum = 
    let rnd = System.Random() 
    let first = rnd.Next(minNum, maxNum) 
    let second = rnd.Next(minNum, maxNum) 
    let third = first + second 
    first, second, third 

mà có thể được gọi như thế này và hoạt động tốt (luôn luôn đưa ra một số ngẫu nhiên mới) (khi sử dụng F # tương tác)

foo 0 50 

khi cố gắng để tạo ra một danh sách các TripleS ngẫu nhiên như thế này

List.init 100 (fun index -> foo 0 50) 

Tôi muốn đây là danh sách 100 bộ ba ngẫu nhiên, nhưng thay vào đó tất cả chúng đều có cùng giá trị. Tôi có thể thấy rằng hàm không phụ thuộc vào chỉ mục và do đó không cần phải tính toán lại, nhưng tôi không chắc chắn cách làm việc xung quanh nó (tôi đã cố gắng giới thiệu chỉ mục dưới dạng biến giả không sử dụng, cũng đã cố gắng giới thiệu chỉ mục dưới dạng hạt giống ngẫu nhiên, nhưng không được giúp đỡ)

Trả lời

14

Giả sử rằng mã của bạn không hoạt động như bạn muốn là trình biên dịch áp dụng sai một số loại trừ biểu hiện phụ phổ biến, khiến foo 0 50 chỉ được đánh giá một lần . Đây không phải là trường hợp. Trình biên dịch biết rất rõ rằng các hàm có thể không tinh khiết và sẽ không thực hiện các tối ưu hóa sẽ phá vỡ với mã không thuần khiết (trừ khi mã cụ thể đang được tối ưu hóa có thể được chứng minh là thuần túy). Vì vậy, bạn không phải lo lắng về việc làm cho trình biên dịch nghĩ rằng bạn đang sử dụng đối số.

Vấn đề không phải là foo 0 50 được gọi chỉ một lần - nó thực sự được gọi là 100 lần như bạn muốn. Vấn đề là nó trả về cùng một giá trị cho mỗi 100 lần nó được gọi.

Nhưng tại sao nó sẽ làm điều đó khi nó trả về các giá trị khác nhau khi bạn kiểm tra nó theo cách thủ công?

Vì bạn tạo đối tượng Ngẫu nhiên mới mỗi khi bạn gọi foo. Vì bạn không cung cấp một giá trị hạt giống cho đối tượng ngẫu nhiên đó, nó sẽ được hạt giống với thời gian hệ thống hiện tại. Vì vậy, nếu bạn gọi hàm nhiều lần với một số thời gian trôi qua ở giữa, nó sẽ trả về các giá trị khác nhau mỗi lần. Tuy nhiên nếu bạn gọi nó 100 lần trong một khoảng thời gian ngắn như vậy mà thời gian hệ thống không thay đổi ở giữa, bạn sẽ nhận được cùng một giá trị 100 lần.

Vì vậy, giải pháp cho vấn đề của bạn là sử dụng lại cùng một đối tượng ngẫu nhiên, thay vì tạo một đối tượng mới mỗi lần foo được gọi.

+0

cảm ơn rất nhiều, hoạt động! –

3

Để bổ sung cho câu trả lời sepp2k với một số mã:

let rnd = System.Random() 

let foo minNum maxNum = 
    let first = rnd.Next(minNum, maxNum) 
    let second = rnd.Next(minNum, maxNum) 
    let third = first + second 
    first, second, third 
11

Hãy thử điều này để thay thế. Nó sẽ tái sử dụng các đối tượng ngẫu nhiên cùng mà không cần phải giữ một khoảng trong phạm vi chính của bạn:

let foo = 
    let rnd = System.Random() 
    fun minNum maxNum -> 
     let first = rnd.Next(minNum, maxNum) 
     let second = rnd.Next(minNum, maxNum) 
     let third = first + second 
     first, second, third 

Cũng lưu ý rằng tiếp không threadsafe vì vậy nếu bạn có ý định sử dụng foo từ một số chủ đề bạn cần phải thêm một số khóa để Kế tiếp.

Các vấn đề liên quan