Katta tasodifiy sonlarni qanday yaratish mumkin C

Men umumiy kalit shifrlash algoritmida (p va q) foydalanish uchun 2 ^ 64 ning C ... (100000000 - 999999999) tartibida katta tasodifiy sonlarni yaratish usulini izlayapman.

Men 2 ^ 64dan (ya'ni, 100000000 dan kichikroq) kichik raqamni yaratishni xohlamayman.

Menga yordam beradigan biror narsa bormi?

9
[100000000 - 999999999] 900 000 000 turli qiymatga ega. Bu sonlar soni 64 emas, balki 30 bitni tashkil qiladi.
qo'shib qo'ydi muallif chux, manba
2 ^ 64 qiymati 999999999dan kattaroq.
qo'shib qo'ydi muallif undur_gongor, manba

6 javoblar

tAsodifiy() 64bit tizimdA 64 bit bo'lishi kerAk bo'lgAn uzunligi qAytArAdi. AgAr siz 32bit tizimdA bo'lsAngiz, quyidAgilArni AmAlgA oshirishingiz mumkin:

#include 

uint64_t num;

/* Add code to seed rAndom number generAtor */

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

// enforce limits of vAlue between 100000000 And 999999999
num = (num % (999999999 - 100000000)) + 100000000;

Shu bilAn bir qAtordA NIX tizimidA siz/dev/tAsodifiy tAmpondA o'qishingiz mumkin:

#include 
#include 
#include 
#include    

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

// enforce limits of vAlue between 100000000 And 999999999
num = (num % (999999999 - 100000000)) + 100000000;

A

12
qo'shib qo'ydi
2 ^ 32 emas, balki RAND_MAX da 2 ^ 31 .
qo'shib qo'ydi muallif Chiel ten Brinke, manba
Raq = (Raqam << 32) | Rand (); "Agar siz 32bitda bo'lsangiz", unda RAND_MAX = ehtimol 2 ^ 31-1 yoki undan kamroq. Keyin num = (son, 32, 32) | Rand (); , har doim bir xildagi son hosil qiladi va ba'zi bitlar bir xil holatda tozalanadi. num% (999999999 - 100000000) bu muammoni hali ham bir xil taqsimlashning kamligi evaziga taqsimlashga yordam beradi.
qo'shib qo'ydi muallif chux, manba
u32 , kichik raqamlarni bir xil tarzda taqsimlangan deb hisoblasa, bunday birlashtirilgan raqam u64 = (u32 << 32) | u32 da bormi?
qo'shib qo'ydi muallif this, manba
Bu "100000000 dan kattadan kichik raqamni yaratishni istamasman" talabiga javob bermaydi.
qo'shib qo'ydi muallif undur_gongor, manba
Yaxshiroq, lekin endi 805933941 (2 ^ 64 -1 mod 899999999) dan yuqori raqamlar quyidagi raqamlardan bir oz pastroq bo'lishi mumkin ;-)
qo'shib qo'ydi muallif undur_gongor, manba
100000000 pastki chegarasining tasodifiy sonini va 999999999 yuqori chegarasini hosil qilish uchun num = (%% (999999999 - 100000000)) + 100000000 qatorini qo'shing.
qo'shib qo'ydi muallif David M. Syzdek, manba
rand() kodi RAND_MAX tomonidan cheklangan va u zaruriy emas. 2 ^ 32 . Va siz hali ham srand() ga o'tishingiz kerak bo'lgan biror narsaga muhtojmiz. /dev/tasodifiy funksiyasi ham boshqa platformalar .
qo'shib qo'ydi muallif Piotr Praszmo, manba

Siz 8 baytli ikkita ikkita 4 baytli tasodifiy integrallarni birlashtira olasiz:

#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.

EDIT -ni tanlang

@Banthar RAND_MAX 2 ^ 32 bo'lishi shart emasligini va buning hech bo'lmaganda 2 ^ 16 bo'lishi kafolatlangan deb o'ylayman. to'rtta 2-bayt raqamlarni birlashtirib, ishonch hosil qilish uchun:

uint64_t random = 
  (((uint64_t) rand() <<  0) & 0x000000000000FFFFull) | 
  (((uint64_t) rand() << 16) & 0x00000000FFFF0000ull) | 
  (((uint64_t) rand() << 32) & 0x0000FFFF00000000ull) |
  (((uint64_t) rand() << 48) & 0xFFFF000000000000ull);
9
qo'shib qo'ydi
Bir-biridan mustaqil: RAND_MAX 2 ^ 32 bo'lishi mumkin emas. Bu (2 ^ 32) - 1 bo'lishi mumkin. Biroq, bu ham kam uchraydi. (2 ^ 31) - 1 yoki (2 ^ 15) - 1 umumiy qiymatiga ega INT_MAX ga o'xshash. C kodi RAND_MAX ni 2 ^ 16 emas, balki (2 ^ 15) - 1 deb belgilaydi.
qo'shib qo'ydi muallif chux, manba
| o'rniga raqamlarni birlashtirish uchun ^ foydalanayotgan bo'lsangiz, maskeleme haqida xavotirlanishga hojat yo'q.
qo'shib qo'ydi muallif caf, manba

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

7
qo'shib qo'ydi
Avgust 2018da openssl.org/docs/crypto/rand.html o'lik havolasi Bog'dagi muammolardan faqat biri javob.
qo'shib qo'ydi muallif chux, manba
Yoki Windows Vista va Windows Vista'da BCryptGenRandom yuqori.
qo'shib qo'ydi muallif Alexey Frunze, manba
+1: bu rand() dan foydalanib, bu xavfsizlik teshigi ( rand() chiqishini taxmin qilish juda ham qiyin emas)
qo'shib qo'ydi muallif Frank Farmer, manba

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.

Shunday qilib, katta tasodifiy sonli kichik tasodifiy sonlarni yaratishingiz mumkin.

3
qo'shib qo'ydi
B oralig'i [0 ... (2 ^ n) -1 bo'lmasa, L = (2 ^ n) * A + B muammo hisoblanadi. Agar B oralig'i keng (va yana kuch-of-2) bo'lsa, L = (2 ^ n) * A ^ B dan foydalanish yaxshiroq. L = (max_possible_value_of_B + (tip_of_L)) uchun eng yaxshisidir 1) * A + B
qo'shib qo'ydi muallif chux, manba
u32 , kichik raqamlarni bir xil tarzda taqsimlangan deb hisoblasa, bunday birlashtirilgan raqam u64 = (u32 << 32) | u32 da bormi?
qo'shib qo'ydi muallif this, manba
Bu yerda. O'ylaymanki, ha, lekin matematikatchini so'rashingiz kerak.
qo'shib qo'ydi muallif Basile Starynkevitch, manba
L, n, A va b harflari nimani anglatadi? Iltimos, iltimos tushuntirib bera olasizmi?
qo'shib qo'ydi muallif Ameen, manba

Bilaman, ehtimol, OliCharlesworth tomonidan qabul qilinadigan bo'laman, lekin rand() yordamida shkala bilan almashtiriladi. Bu stdlib.h da hamma qatorni qamrab olish uchun siz xaritada bo'shliqlarni to'ldirish uchun uni kichikroq rand() ga qo'shishingiz kerak.

3
qo'shib qo'ydi

Yoki INDEPENDENT urug'lari bilan ikkita tasodifiy raqamli generatorni ishlatishingiz mumkin va ularning chiqish raqamlarini birgalikda taklif qilishingiz mumkin. Bu siz 2 ^ 64 oralig'idagi davrni o'z ichiga olgan RNGning 64 bitli sonini xohlaysizmi. Faqat vaqtga bog'liq bo'lgan standart qo'ng'iroqni ishlatmang, chunki har bir generator uchun bir xil urug'lar bo'ladi. To'g'ri, men bilmayman ...

1
qo'shib qo'ydi