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
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.
Nasıl C rasgele tamsayı sayı üretmek m...
Nasıl bir TSQL Seçin her satır için ra...
Nasıl üretmek için bash adım n? (artış...
Nasıl alfa-sayısal rasgele bir dize ol...
Nasıl Ruby rastgele bir sayı almak içi...