Toon posts:

C++ rand() icm srand() is niet echt random :(

Pagina: 1
Acties:

Verwijderd

Topicstarter
code:
1
2
3
4
5
srand(time(NULL));   

//float ratio    = rand() / RAND_MAX;

printf("num: %i\n", rand());

Ik heb het bovenstaande stukje code geschreven. De random lijkt echter niet echt random. Ik wil namelijk dat ik echt een random getal krijg tussen de nul en één.

Dit stukje code wordt elke 100 frames aangeroepen(het betreft een opengl applicatie en elke keer na 100 frames wordt dit aangeroepen). Maar als ik dus de waardes van rand() bekijk zijn ze niet echt random, maar volgen ze elkaar op: :/

code:
1
2
3
4
5
6
num: 6150
num: 6154
num: 6160
num: 6167
num: 6170
num: 6177


Rara, hoe kan dat en hoe los ik dat op? :)

PS. Ik heb al een aantal topics doorgelezen hier op GoT, maar heb DE oplossing niet kunnen vinden.

edit:
het lijkt erop dat hij gewoon door telt. Toen ik de applicatie nog een keer starte nadat ik bovenstaande output gecopy paste had begon ie ergens bij 7200, daarna bij 7400 in de buurt. Ik begrijp er geen snars van :D

[ Voor 14% gewijzigd door Verwijderd op 28-05-2003 19:16 ]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Ik geloof dat het de bedoeling is dat je hem maar 1x per applicatie-run seed. En dan zovaak als je wil random kan aanroepen.

Nu krijg je een 'random' value die afhankelijk is van de tijd enzo :)

Verwijderd

Topicstarter
dat ziet er inderdaad wat randomer uit ja :), geloof dat het nu goed werkt, bedankt :)

Verwijderd

Topicstarter
nou, dan gooien we meteen even het volgende probleem ertegen aan(voor als er toevallig nog iemand langs kom :D)
code:
1
double ratio = (double)(rand() / RAND_MAX);

levert altijd 0.000000 op? :/

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

hoe groot is rand_max en is dat wel een double?

Verwijderd

Topicstarter
nee dus :(
RAND_MAX was een int, en rand() leverde de int op.
en int/int levert altijd een int op kennelijk :)
ik cast ze nu beide naar double en het werkt :/

Raar taaltje dat c++ :P (ik ben een echte Java man :D)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

In java moet je dat ook casten ;)

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 21-06 17:10
Misschien kleine aanvullig:
Ik heb een keer een linkedlist zitten bouwen, en 1.000.000 random getallen toegevoegd op deze manier. Kwam tot de conclusie dat ie niet hoger komt dan 32.565 (precies een int dus). Misschien iets om rekening mee te houden?

edit:

Die getallen heb ik ff uit m'n hoofd gedaan... Zou idd best 32.767 kunnen zijn

[ Voor 17% gewijzigd door riezebosch op 29-05-2003 16:07 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je bedoelt vast 32767, en dat is de max van een signed short op 32 bits machines
De default implementatie van VC++ zuigt imho, juist door die 'maar' 15 bits precisie
Je zou natuurlijk dit kunnen doen:

C++:
1
2
3
4
int myRandom ()
{
    return (rand () << 15) | rand ();
}


Maar zelf gebruik ik altijd de rand () implementatie die bij DJGPP zit:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Copyright (C) 1994, 1996, 1998, 1999 DJ Delorie */

#define DJ_RAND_MAX 0x7fffffff

static unsigned __int64 next = 1;

int dj_rand(void)
{
    /* This multiplier was obtained from Knuth, D.E., "The Art of
    Computer Programming," Vol 2, Seminumerical Algorithms, Third
    Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */

    next = next * 6364136223846793005L + 1;
    /* was: next = next * 0x5deece66dLL + 11; */
    return (int)((next >> 21) & DJ_RAND_MAX);
}

void dj_srand (unsigned seed)
{
    next = seed;
}


En voila, 31 bits precisie :)

[ Voor 7% gewijzigd door .oisyn op 28-05-2003 22:52 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 10-07 04:13

PommeFritz

...geen friet

Eh 32.565 een int? een int in C++ en Java is meestal max. 0x7FFFFFFF (2147483647). Ben je niet in de war met een 16-bit short, max 0x7FFF (32767).

edit: laat maar, net te laat :/

[ Voor 14% gewijzigd door PommeFritz op 28-05-2003 22:48 ]

FireFox - neem het web in eigen hand


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

PommeFritz schreef op 28 May 2003 @ 22:47:
Eh 32.565 een int? een int in C++ en Java is meestal max. 0x7FFFFFFF (2147483647). Ben je niet in de war met een 16-bit short, max 0x7FFF (32767).
De grootte van een int is niet vastgelegd in de C/C++ standaard (in Java echter wel, daar is ie altijd 32 bits)

Vroeger onder DOS was een int gelijk aan een short. Tegenwoordig is ie gelijk aan een long. Als je in windows een 64 bits app maakt is ie gelijk aan een __int64

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

En onder x86-linux/unix is een long weer 32 bits, toch? Een long long is pas weer 64 bits. Lekker verwarrend allemaal :o

[ Voor 4% gewijzigd door ACM op 28-05-2003 23:22 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Voor de "betere" random-number generators kun je ook op boost kijken; die zijn AFAIK portable naar alle systemen (itt de 64-bit longs uit DJGPP).

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Onno
  • Registratie: Juni 1999
  • Niet online
.oisyn schreef op 28 May 2003 @ 22:49:
De grootte van een int is niet vastgelegd in de C/C++ standaard (in Java echter wel, daar is ie altijd 32 bits)
Ik dacht dat een int gewoon zo groot was als de datagrootte waar je cpu mee werkt. Voor Java is dat op zich niet echt anders, alleen heb je overal dezelfde (virtuele) CPU, onafhankelijk van het fysieke platform. Verder geldt overal dat short <= int <= long, dus pas op 64 bits cpu's is het nodig om een long groter te maken dan de 32 bits die hij op 16 en 32 bits cpu's veelal is.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

ACM schreef op 28 May 2003 @ 23:22:
En onder x86-linux/unix is een long weer 32 bits, toch? Een long long is pas weer 64 bits. Lekker verwarrend allemaal :o
Onder Win32 ook hoor, dus weinig verwarrend :)

Mocht je absolute duidelijkheid willen, iedere compiler waar ik ooit mee heb gewerkt ondersteunt __int8, __int16, __int32 en __int64 (al of niet prefixed met het 'unsigned' keyword).

[ Voor 3% gewijzigd door curry684 op 29-05-2003 02:34 ]

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

ACM schreef op 28 May 2003 @ 23:22:
En onder x86-linux/unix is een long weer 32 bits, toch? Een long long is pas weer 64 bits. Lekker verwarrend allemaal :o
ik zei niets over long, ik had het over int :)
MSalters schreef op 28 May 2003 @ 23:27:
Voor de "betere" random-number generators kun je ook op boost kijken; die zijn AFAIK portable naar alle systemen (itt de 64-bit longs uit DJGPP).
djgpp gebruikt overigens gcc, dus het was een long long. Ik heb die zelf omgezet naar __int64 zodat ik 'm kon gebruiken in MSVC++
.edit: woei ik merk ineens dat VC++ 7.1 ook long long ondersteund _O_
Onno schreef op 28 May 2003 @ 23:31:
[...]

Ik dacht dat een int gewoon zo groot was als de datagrootte waar je cpu mee werkt.
Vaak is dat zo, maar ik betwijfel of dat ook daadwerkelijk vast staat.
Voor Java is dat op zich niet echt anders, alleen heb je overal dezelfde (virtuele) CPU, onafhankelijk van het fysieke platform.
Dus is ie gefixed op 32 bits (dat is geloof ik ook gewoon een definitie in de standaard, itt C/C++, dat verschil wilde ik duidelijk maken)
Verder geldt overal dat short <= int <= long, dus pas op 64 bits cpu's is het nodig om een long groter te maken dan de 32 bits die hij op 16 en 32 bits cpu's veelal is.
En char <= short ;)
maar idd
Alleen dan mist er een 32 bits datatype

Ik ging eens kijken hoe dat nou zat, toen las ik ineens dit:
An int and a long are 32-bit values on 64-bit Windows operating systems.
bron

dus int en long veranderen helemaal niet :?
Nou ja dat scheelt ook weer veel porting issues :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • TlighT
  • Registratie: Mei 2000
  • Laatst online: 22-03 10:40
.oisyn schreef op 29 May 2003 @ 18:03:
Ik ging eens kijken hoe dat nou zat, toen las ik ineens dit:

[...]


bron

dus int en long veranderen helemaal niet :?
Nou ja dat scheelt ook weer veel porting issues :)
Dat klopt. Maar Linux 64bit is dus weer LP64, dus int 32 bits en long 64 bits (op een intel tenminste). Persoonlijk vind ik dat beter omdat je dan ook een 64 bits type hebt, maar je zult wel je code moeten aanpassen als die veronderstelt dat sizeof(int)==sizeof(long) en dat hoeft bij Windows dus niet.

Edit: onder C#/.NET is trouwens een int 32 bits en een long 64 bits.

[ Voor 9% gewijzigd door TlighT op 29-05-2003 21:54 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
.oisyn schreef op 29 May 2003 @ 18:03:
[...]

djgpp gebruikt overigens gcc, dus het was een long long. Ik heb die zelf omgezet naar __int64 zodat ik 'm kon gebruiken in MSVC++
.edit: woei ik merk ineens dat VC++ 7.1 ook long long ondersteund _O_
long long is C99, en er is een vrij grote consensus binnen de C++ commissie dat het een idioot idee is ;) maar geen incompabiliteit waard. Het komt dus redelijk zeker in C++0x. Ik denk dat alle compilers die nu __int64 hebben daar een typedef voor long long van gaan maken.

Overigens: Zelfs als alle compilers __int8 hebben is het nog maar de vraag of de code daarmee portable is: Is het een type of een typedef? Kun/Moet je een aparte overload ervoor maken?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

TlighT schreef op 29 mei 2003 @ 21:47:
[...]

Dat klopt. Maar Linux 64bit is dus weer LP64, dus int 32 bits en long 64 bits (op een intel tenminste). Persoonlijk vind ik dat beter omdat je dan ook een 64 bits type hebt, maar je zult wel je code moeten aanpassen als die veronderstelt dat sizeof(int)==sizeof(long) en dat hoeft bij Windows dus niet.

Edit: onder C#/.NET is trouwens een int 32 bits en een long 64 bits.
Er zijn wel meer problemen, denk aan pointers die altijd gewoon 4 bytes waren, maar nu 64 bits zijn door de grotere geheugenadressering, en dus dan ineens 8 bytes innemen. Ook geeft dat nogal problemen bij het reinterpret_casten naar int

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • mvdejong
  • Registratie: Juni 2000
  • Laatst online: 29-11-2024

mvdejong

When does the hurting stop ?

Echte random-getallen kun je op een computer niet krijgen, tenzij je externe factoren kunt meenemen. Een random-number-generator begint een berekening a.d.h.v. een initiele toestand, en genereert dan een reeks die pseudo-random is, en evenwichtig verdeeld is tussen de minimale en maximale waarde die de RNG kan opleveren.

De initiele toestand wordt gewoonlijk bepaald door een "seed", waarbij het zo is dat dezelfde seed steeds dezelfde reeks pseudo-random getallen oplevert (opzettelijk, want dan kun je in een test-situatie reproduceerbare reeksen gegevens verkrijgen).

Je kunt wel proberen voor elk nieuw pseudo-random-getal een nieuwe seed te nemen, maar dat werkt alleen betrouwbaar als je je seed goed random kunt kiezen, anders is het zelfs slechter dan uitgaan van een seed en een hele reeks genereren.

RNG-implementaties die niet expliciet een seed meekrijgen, kunnen ofwel uitgaan van een standaard-seed, of zelf een seed kiezen, bijv. vanuit de systeem-klok. Veel applicaties gebruiken ook de systeem-klok als seed, maar er zijn andere opties, bijv. het patroon van toets-aanslagen van de gebruiker.

Idealere seeds worden snel exotisch, bijv. het patroon van het aantal deeltjes t.g.v. radio-actief verval in een bepaalde tijd. Dat zou zelfs op zich al bruikbaar kunnen zijn als RNG.

The number of things that Arthur couldn't believe he was seeing was fairly large


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
mvdejong schreef op 30 May 2003 @ 11:01:
Echte random-getallen kun je op een computer niet krijgen, tenzij je externe factoren kunt meenemen. Een random-number-generator begint een berekening a.d.h.v. een initiele toestand, en genereert dan een reeks die pseudo-random is, en evenwichtig verdeeld is tussen de minimale en maximale waarde die de RNG kan opleveren.
Er zijn wat trucen om toch een interne random-source te vinden: De seek-times van harddisks zijn chaotisch temperatuur-afhankelijk. Een klein verschil kan een extra rotatie betekenen.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1