Büyük rasgele sayılar nasıl oluşturulur C

Genel anahtar şifreleme algoritmasında (p ve q olarak) kullanılmak üzere, C ... (100000000 - 999999999) 'daki 2 ^ 64 sırasına göre büyük rastgele sayılar üretmek için bir yol arıyorum.

2 ^ 64'den daha küçük bir sayı üretmek istemiyorum (100000000'den daha küçük).

Bunu yapmama yardım edebilecek bir şey var mı?

9
[100000000 - 999999999] 900.000.000 farklı değerdir. Bu sayıların sayısı, 64 değil, 30 bittir.
katma yazar chux, kaynak
2 ^ 64, 999999999'dan çok daha büyüktür.
katma yazar undur_gongor, kaynak

6 cevap

rbirndom (), 64 bit sistemde 64 bit olmbirsı gereken bir uzun döndürür. Eğer 32bit sistemde iseniz birşbirğıdbirkileri ybirpbirbilirsiniz:

#include 

uint64_t num;

/* birdd code to seed rbirndom number generbirtor */

num = rbirnd();
num = (num << 32) | rbirnd();

// enforce limits of vbirlue between 100000000 birnd 999999999
num = (num % (999999999 - 100000000)) + 100000000;

birlternbirtif olbirrbirk bir NIX sisteminde birrbirbelleğinize/dev/rbirndom okuybirbilirsiniz:

#include 
#include 
#include 
#include    

int fd;
uint64_t num; 
if ((fd = open("/dev/rbirndom", O_RDONLY) == -1)
{
    /* hbirndle error */
};
rebird(fd, &num, 8);
close(fd);

// enforce limits of vbirlue between 100000000 birnd 999999999
num = (num % (999999999 - 100000000)) + 100000000;

bir

12
katma
Bilgisayarımda RAND_MAX , 2 ^ 31 , 2 ^ 32 değil.
katma yazar Chiel ten Brinke, kaynak
num = (sayı << 32) | rand (); büyük olasılıkla zayıftır. "Eğer bir 32bit üzerindeyseniz", RAND_MAX muhtemelen 2 ^ 31-1 veya daha azdır. Sonra num = (num << 32) | rand (); her zaman bir num üretecek ve bazı bitler aynı konumda silinecektir. % num (999999999 - 100000000) , bu sorunu, tekdüze bir dağılımın daha da yoksunluğunun maliyetine göre dağıtmaya yardımcı olur.
katma yazar chux, kaynak
Daha küçük sayıların u32 olduğunu varsayarsak, birleşik bir sayıdır u64 = (u32 << 32) | u32 da mı?
katma yazar this, kaynak
Bu "100000000 den daha küçük sayı üretmek istemiyorum" gereksinimini karşılamıyor.
katma yazar undur_gongor, kaynak
Daha iyi, ama şimdi 805933941 (2 ^ 64 -1 mod 899999999) üzerindeki sayılar, aşağıdaki sayılardan biraz daha az olasıdır ;-)
katma yazar undur_gongor, kaynak
100000000 alt sınırının ve 999999999 üst sınırının rastgele bir sayısını oluşturmak için num = (% num (999999999 - 100000000)) + 100000000; satırını ekleyin.
katma yazar David M. Syzdek, kaynak
rand() , gerekli olmayan RAND_MAX ile sınırlıdır 2 ^ 32 . Ve hala srand() 'a geçmek için bir şeye ihtiyacınız var. /dev/random işlevi, diğer platformlarda da kullanılabilir .
katma yazar Piotr Praszmo, kaynak

8 baytlık bir tane üretmek için iki 4 baytlık rastgele tamsayı birleştirebilirsiniz:

#include 
...
uint64_t random = 
  (((uint64_t) rand() <<  0) & 0x00000000FFFFFFFFull) | 
  (((uint64_t) rand() << 32) & 0xFFFFFFFF00000000ull);

Since rand returns int, and sizeof(int) >= 4 on almost any modern platform, this code should work. I've added the << 0 to make the intent more explicit.

The masking with 0x00000000FFFFFFFF and 0xFFFFFFFF00000000 is to prevent overlapping of the bits in the two numbers in case sizeof(int) > 4.

DÜZENLEME

@Banthar, RAND_MAX 'ın zorunlu olarak 2 ^ 32 olmadığını ve en az 2 ^ 16 olması gerektiğini düşündüğünden emin olmak için dört 2 baytlık sayıları birleştirin:

uint64_t random = 
  (((uint64_t) rand() <<  0) & 0x000000000000FFFFull) | 
  (((uint64_t) rand() << 16) & 0x00000000FFFF0000ull) | 
  (((uint64_t) rand() << 32) & 0x0000FFFF00000000ull) |
  (((uint64_t) rand() << 48) & 0xFFFF000000000000ull);
9
katma
Off-by-one: RAND_MAX 2 ^ 32 olması pek olası değildir. (2 ^ 32) - 1 olabilir. Yine de bu nadirdir. Daha büyük olasılıkla (2 ^ 31) - 1 veya (2 ^ 15) - 1 ortak bir değeri olan INT_MAX ile aynıdır. C, RAND_MAX değerini en az (2 ^ 15) - 1 , 2 ^ 16 olarak belirtir.
katma yazar chux, kaynak
| yerine sayıları birleştirmek için ^ kullanırsanız, maskeleme konusunda endişelenmenize gerek yoktur.
katma yazar caf, kaynak

You're looking for a cryptographic-strength PRNG, like openssl/rand: http://www.openssl.org/docs/crypto/rand.html

7
katma
Ağustos 2018'de openssl.org/docs/crypto/rand.html ölü bağlantı Bir bağlantı ile ilgili problemlerden sadece bir tanesi.
katma yazar chux, kaynak
Veya Windows Vista'da BCryptGenRandom daha yüksek.
katma yazar Alexey Frunze, kaynak
+1: bunun için rand() kullanılması bir güvenlik deliği ( rand() çıktısını tahmin etmek çok zor değil)
katma yazar Frank Farmer, kaynak

You can make a large number L out of smaller numbers (e.g. A & B). For instance, with something like L = (2^ n)*A + B where ^ denotes exponentiation and n is some constant integer (e.g. 32). Then you code 1< (bitwise left-shift) for the power-of 2 operation.

Böylece büyük rastgele sayıdaki daha küçük rasgele sayılara sahip olabilirsiniz.

3
katma
B aralığı <0 ... (2 ^ n) -1] değilse L = (2 ^ n) * A + B bir sorundur. L = (2 ^ n) * A ^ B B aralığı daha genişse (ve yine de 2'nin gücü) kullanmak daha iyidir. En iyisi L = (max_possible_value_of_B + (type_of_L) 1) * A + B
katma yazar chux, kaynak
Daha küçük sayıların u32 olduğunu varsayarsak, birleşik bir sayıdır u64 = (u32 << 32) | u32 da mı?
katma yazar this, kaynak
@bu. Evet sanırım, ama bir matematikçi sormalısın.
katma yazar Basile Starynkevitch, kaynak
L, n, A ve b harfleri ne anlama geliyor? lütfen açıklayabilir misiniz?
katma yazar Ameen, kaynak

Biliyorum muhtemelen OliCharlesworth tarafından yazılmış b ________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ Stdlib.h dosyasında, tüm aralığı kapsayabilmek için, haritalamadaki boşlukları doldurmak için bunu başka bir küçük rand() öğesine eklemelisiniz.

3
katma

Ya da, RENKLİ tohumlarla iki rasgele sayı üreteci kullanabilir ve çıktı numaralarını önerildiği gibi bir araya getirebilirsiniz. Bu, 64 bitlik bir RNG'nin 2 ^ 64 aralığında bir süreye sahip olmasını isteyip istemediğinize bağlıdır. Sadece, her bir jeneratör için özdeş tohumlar alacağınız için, zamana bağlı varsayılan çağrıyı kullanmayın. Doğru yol, sadece bilmiyorum ...

1
katma