2011-09-18 26 views
5

F # içinde rasgele bir sayı "üreteci" geliştirmeye çalışıyorum. F # işlevinde birden çok değerlendirmeyi zorla F #

başarıyla aşağıdaki işlevi yarattı:

let draw() = 
    let rand = new Random() 
    rand.Next(0,36) 

Bu iyi çalışır ve o 0 ile 36 Bununla

arasında bir sayı üretir, bu fonksiyonu birkaç kez çalıştırılan bir işlevi oluşturmak çalışıyorum .

Ben draw anlama için yalnızca bir kez değerlendirilir olarak sadece tek bir sonuç almak, Ancak şu

let multipleDraws (n:int) = 
    [for i in 1..n -> draw()] 

çalıştı.

draw işlevinin birden çok uygulamasını nasıl zorlayabilirim?

cevap

8

Sorun, Rastgele türündedir. Bir tohum üretmek için bilgisayarın zamanını kullanır ve daha sonra rasgele sayıları üretir. Pratik olarak çağrıların zamanı aynı olduğu için, aynı tohum üretilir ve aynı zamanda geri dönen sayılarla aynıdır.

Bu sorununuzu çözecektir: o zaman

let draw = 
    let rand = new Random() 
    fun() -> 
    rand.Next(0,36) 

Ve:

let multipleDraws (n:int) = 
    [for i in 1..n -> draw()] 
+0

Teşekkürler, ama anlamıyorum, size çözüm kullanarak, neden hala tohumla aynı problemi yaşamadım? – SRKX

+0

Rastgele kurucuyu çağırırken, geçerli bilgisayarın zamanına göre bir tohum üretirsiniz. Ardından, Sonraki yönteme yapılan her çağrı, önceki tohuma dayalı yeni bir tohum * oluşturur ve zamana dayalı değildir.Artık süreye bağlı olmadığınızdan, aramalarınızın aynı makine saatinde yapılması önemli değildir. 'Draw' vücudun bir ilk satırı neler görmek için gibi eklemek isteyebilirsiniz' printfn "denir çizmek" ': –

+2

@SRKK yalnızca bir çıkış görürsünüz. Aslında liste anlayışı içinde çağrılan '- Sizin' draw' fonksiyon Yanıtta bir imzayla anonim işlevini döndürür iken '(> int birimi), tamsayılar döndü. Bu anonim işlev, “rand” değerini bir kapanışa yaklaştırır, “rand” nin kendisi sadece bir kez tohumlanır. –

6

Ramon'un cevabını açıkla yardımcı olmak için bu ekleme.

Bu kod bir lambda işlevi kullanmaktadır.

let draw = 
    let rand = new Random() 
    fun() -> 
    rand.Next(0,36) 

Lambda işlevine bir ad verirseniz neler olup bittiğini anlamak daha kolay olabilir.

let draw = 
    let rand = new Random() 
    let next() = 
     rand.Next(0,36) 
    next 

Değişken çizim sonraki işleve atanıyor. Randevuyu doğrudan görmek için rand ve sonraki çekim kapsamını dışarı taşıyabilirsiniz. Bunu SRKX en örnekte defalarca denirken Ramon'un yanıtında yeni Rastgele yalnızca bir kez denir yukarıdaki koddan görebilirsiniz

let rand = new Random() 
let next() = 
    rand.Next(0,36) 
let draw = next 

.

Ramon Random'ın belirttiği gibi, rastgele bir tohuma dayalı olarak bir sayı dizisi oluşturur. Aynı tohumu kullanırsanız her zaman aynı sayı dizisini oluşturur. Bu new Random(2) gibi rastgele bir tohum geçirebilirsiniz. Eğer bir değeri geçmezseniz, o andaki zamanı kullanır. Yani, bir rastgele yeni bir kerede birden çok kez rastgele çağırırsanız, muhtemelen aynı tohuma sahip olacaktır (çünkü zaman değişmedi). Tohum değişmezse, dizinin ilk rastgele sayısı her zaman aynı olacaktır. SRKX'in orijinal kodunu denerseniz ve yeterince büyük bir sayıya sahip birden fazla sayıda Çoklu Arayışı çağırırsanız, döngü sırasında zaman değişecektir ve sık sık değişen bir sayı dizisini geri alacaksınız.

+0

Ek açıklama için teşekkürler! daha da açık hale getirir. – SRKX