Portál AbcLinuxu, 14. května 2025 19:38

Dotaz: C++ zvyseni RAND_MAX

24.3.2012 12:10 Michal Reynolds
C++ zvyseni RAND_MAX
Přečteno: 462×
Odpovědět | Admin
Zdravim, potreboval bych generovat v C (pseudo)nahodna cisla z intervalu 0 - 4294967295, ale funkce rand() je generuje pouze do konstanty RANDMAX, coz je 2147483647. Jde toto nejakym zpusobem obejit?
Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

AraxoN avatar 24.3.2012 13:10 AraxoN | skóre: 47 | blog: slon_v_porcelane | Košice
Rozbalit Rozbalit vše Re: C++ zvyseni RAND_MAX
Odpovědět | | Sbalit | Link | Blokovat | Admin
Buď môžeš rovno čítať 4 bajty z /dev/urandom, alebo volať rand() dvakrát, čím dostaneš 62 pseudonáhodných bitov a z nich si potom vybrať tých 32 (napr. prvých 16 z prvého volania, druhých 16 z druhého).
7.4.2012 00:41 l4m4
Rozbalit Rozbalit vše Re: C++ zvyseni RAND_MAX
Volat random() dvakrát bych -- pokud nejsou k disposici knihovny s lepšími generátory (MT, Tausworthe, MWC, ISAAC, ...), což běžně jsou -- asi doporučil, nevadí-li snížení efektivity dané nutností generovat dvě čísla. Rozhodně spíš než nějaké matlání lineárních kongruentních generátorů (s příšenými vlastnostmi), o kterých píší níže jiní. Není-li rychlost klíčová, tak to nevadí.

Je-li rychlost klíčová, tak jednak se dá napsat wrapper, který ten to druhé náhodné číslo, z nějž je zapotřebí jen jeden bit, cacheuje a používá z něj bity postupně. Ale spíš je pak zapotřebí používat jiné generátory než systémový random(), umožnit inlinovat kód generování náhodnného čísla, ...
24.3.2012 13:31 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
Rozbalit Rozbalit vše Re: C++ zvyseni RAND_MAX
Odpovědět | | Sbalit | Link | Blokovat | Admin
Pokud na tom nezáleží tak třeba:
#include <iostream>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <iomanip>

int main()
{
  srand(time(NULL));
  std::cout << " RAND_MAX: "  << RAND_MAX << std::endl;
  uint32_t r = rand() % 2147483648;
  r += rand() % 2147483648;
  std::cout << " 31bit: "<< std::setw(10) << std::hex <<  r << std::endl;
  r = ((rand() % 256) << 24) | ((rand() % 256) << 16) | ((rand() % 256) << 8) | ((rand() % 256)) ;
  std::cout << "  8bit: " << std::setw(10) << std::hex<<  r << std::endl;
  return 0;
}
To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
6.4.2012 17:23 ::: | skóre: 14 | blog: e_lama
Rozbalit Rozbalit vše Re: C++ zvyseni RAND_MAX
Příloha:
vim ze pises "pokud na tom nezalezi", ale i tak bych upozornil ze hlavne ten prvni zpusob je hodne spatnej. Problem je ze cisla priblizne uprostred intervalu se daji ziskat vice zpusoby nez cisla na kraji. Napr 0 ziskam jenom jednim zpusobem: 0+0, ale 100 ziskam hodne zpusobama 0+100, 1+99, 2+98, ...

zkousel jsem kod
#include <iostream>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <iomanip>
 
int main()
{
        int cnt[256] = {0, };

        for (int i = 0; i < 100000; ++i)
        {
                uint32_t r = rand() % 128;
                r += rand() % 128;
                ++cnt[r];
        }
        
        for (int i = 0; i < 256; ++i)
        {
                std::cout << cnt[i] << "\n";
        }
}
a dava to distribuci co je v priloze.

Ten druhej zpusob je lepsi, nekde jsem ale cetl ze u "linear congruential generatoru" (kterej je predpokladam pouzitej v rand()) maji spodni bity kratsi periodu nez horni, proto by mozna bylo lepsi pouzit deleni misto modula.

Puvodnimu autorovy bych doporucil:

- pokud potrebujes "cryptographically secure" generator tak pouzi /dev/random

- pokud ne tak se podivej na generatory v c++11

- pokud nemuzes pouzit c++11 tak naprogramuj vlastni linear congruential generator. Navod treba tady: http://en.wikipedia.org/wiki/Linear_congruential_generator. Z tabulky vem hodnoty pro 64 bit. Celkove to budou asi 3 radky kodu...
6.4.2012 21:03 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
Rozbalit Rozbalit vše Re: C++ zvyseni RAND_MAX
Napsal jsem tam „pokud na tom nezáleží“, protože vím, že to není „bezpečné“ řešení, ale je to jednoduché a rychlé. Na bezpečné řešení se dá použít třeba i openssl.
To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.