SORU
24 Mart 2010, ÇARŞAMBA


Nasıl bir aralıkta rasgele sayı üretmek için

Bu daha önce yayınlanan bir soru izleyin

How to generate a random number in C?

Belirli bir aralıkta rasgele bir numara, 1-6 olarak üretebilir bir zar iki taklit edecek şekilde olmasını dilerim.

Bunu nasıl yapıyor hakkında gitmek istiyorsunuz?

CEVAP
27 Temmuz 2011, ÇARŞAMBA


Tüm cevaplar şimdiye kadar matematiksel olarak yanlış. Dönen rand() % N gelmez düzgün bir sayı aralığı [0, N) sürece N böler uzunluğu aralığı rand() döner (yani bir güç 2). Ayrıca, rand() modüllerine bağımsız olup, hiç bir fikrim var: onlar gitmek mümkün üniforması ama çok rastgele olan 0, 1, 2, ...,. Yapmak makul görünüyor sadece varsayım rand() Poisson dağılımı ortaya koyar: büyük bir olasılıkla eşit ve bağımsız olarak aynı boyutta iki örtüşmeyen subintervals. Değerleri sonlu bir küme için, bu üniformayı dağıtılması ve rand() değerleri güzel dağılmış da sağlar.

Bunun anlamı yalnızca doğru şekilde değişim aralığı rand() ayrı ayrı kutuları; örneğin, RAND_MAX == 11 ve bir dizi 1..6 atamanız gerekir {0,1} 1 {2,3} 2, ve benzeri. Bu ayrık, eşit büyüklükte aralıklarla ve böylece eşit ve bağımsız olarak dağıtılır.

Kayan nokta bölme kullanımı öneri matematiksel olarak mümkün değildir ama prensip olarak yuvarlama sorunları muzdarip. Belki de double yüksek-yeterli; belki de değil. Ve anlamaya olmasını istemiyorum bilmiyorum; herhangi bir durumda, cevabı sistemden sisteme göre değişir.

Doğru yolu tamsayı aritmetik kullanmaktır. Yani, aşağıdaki gibi bir şey istiyorum:

#include <stdlib.h> // For random(), RAND_MAX

// Assumes 0 <= max <= RAND_MAX
// Returns in the half-open interval [0, max]
long random_at_most(long max) {
  unsigned long
    // max <= RAND_MAX < ULONG_MAX, so this is okay.
    num_bins = (unsigned long) max   1,
    num_rand = (unsigned long) RAND_MAX   1,
    bin_size = num_rand / num_bins,
    defect   = num_rand % num_bins;

  long x;
  do {
   x = random();
  }
  // This is carefully written not to overflow
  while (num_rand - defect <= (unsigned long)x);

  // Truncated division is intentional
  return x/bin_size;
}

Döngü tamamen homojen bir dağılım elde etmek için gereklidir. Örneğin, size verilen rasgele sayılar, 0 ve 2 istediğiniz sadece olanları, 0 1, sen çekmeye devam et kadar alamazsın 2; değil zor onay verir 0 veya 1 ile eşit olasılık. Bu yöntem de adet farklı kodlanmış olsa da kendi cevap verdi, O bağlantı olarak açıklanmıştır. Daha iyi bir dağıtım rand() man sayfasına tarafından belirtildiği gibi) olduğu gibi rand() yerine random() kullanıyorum.

Eğer varsayılan aralığın dışında rasgele değerleri elde etmek istiyorsanız [0, RAND_MAX], sonra bir şeyler zor yapmak zorundasın. Belki de en kestirme olduğu için belirli bir fonksiyon random_extended() çeker n bit (kullanarak random_at_most()) ve döner [0, 2**n) ve Uygula random_at_most() random_extended() yer random() (2**n - 1 yer RAND_MAX) çekme rasgele değeri daha az 2**n, varsayarak bir sayısal tür koyabilirim böyle bir değer. Son olarak, tabii ki, [min, max] değerleri negatif değerler de dahil olmak üzere min random_at_most(max - min 1) kullanarak alabilirsiniz.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Austin Evans

    Austin Evans

    5 AĞUSTOS 2007
  • RayperEnglishKnight

    RayperEnglis

    24 Kasım 2008
  • The Warp Zone

    The Warp Zon

    24 AĞUSTOS 2007