Avatar billede anarchy Nybegynder
02. november 2002 - 18:55 Der er 23 kommentarer og
1 løsning

Tilfældige tal

Hvordan vil en funktion der kan genere et tilfædligt tal ud. Man skal kunne sætte en øvre og nedre grænse, alt så for ekembel kunne returnere et tilfældigt tal mellem 1 og 5. Og helst af typen int.

Må gerne se til_feldig(nedre, ovre) agtig ud.
Avatar billede mickni33 Nybegynder
02. november 2002 - 19:04 #1
Et tal mellem 1 og 6
srand( (unsigned)time( NULL ) );
skal kun bruges en gang i dit program



#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int random;
srand( (unsigned)time( NULL ) );

for(int i=0;i<6;i++){
    int random = rand()%6 + 1;
    cout<<random<<endl;
}
Avatar billede mickni33 Nybegynder
02. november 2002 - 19:07 #2
et tal mellem 1 og 6
srand( (unsigned)time( NULL ) );
skal kun bruges en gang i dit program


#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(){
int random;
int nyrandom;
srand( (unsigned)time( NULL ) );

nyrandom=enfunktion(random);
cout<<nyrandom<<endl;

}

///////////////////////
int enfunktion(int x){
  int x= rand()%6 + 1;
  return x;
}
Avatar billede mickni33 Nybegynder
02. november 2002 - 19:08 #3
sorry int skal væk

int enfunktion(int x){
  x= rand()%6 + 1;
  return x;
}
Avatar billede soreno Praktikant
02. november 2002 - 19:09 #4
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int til_feldig(int nedre, int ovre)
{
    return (rand()%(ovre-nedre))+nedre;
}

int main(int argc, char **argv)
{
    srand(time(0));

    for(int i=0;i<20;i++)
    {
        printf("%i\n", til_feldig(1000, 1010));
    }
   
    return 0;
}
Avatar billede mbulow Nybegynder
02. november 2002 - 19:21 #5
Lille ændring til soreno's nok ellers mest korrekte version :)

  ovre-nedre

skal ændres til

  (ovre-nedre)+1

ellers vil funktionen ikke kunne returnere 'ovre', men kun 'ovre'-1



int til_feldig(int nedre, int ovre)
{
    return (rand()%((ovre-nedre)+1))+nedre;
}
Avatar billede mbulow Nybegynder
02. november 2002 - 19:27 #6
Den version soreno kom med var ellers næsten helt magen til min umiddelbare idé, bare et lille men... :)

Kommer lige til at tænke på. Hvordan kan man pænt klare situationen hvis:
  ovre - nedre
er større end RAND_MAX???

Så vil funktionen jo aldrig kunne returnere 'ovre'. Størst mulige retur-værdi vil da være 'nedre' + RAND_MAX
Avatar billede soreno Praktikant
02. november 2002 - 19:28 #7
det kommer vel egentlig an på hvordan man definerer "mellem nedre og øvre"
det kunne jo være:
[nedre;øvre]
[nedre;øvre[
]nedre;øvre]
]nedre;øvre[
Avatar billede mbulow Nybegynder
02. november 2002 - 19:33 #8
Den anden mulighed kunne jo være at sprede værdierne ud over hele intervallet fra 'nedre' til 'ovre', men så vil der jo være nogle værdier som aldrig bliver ramt...

Findes der mon ikke en eller anden funktion der kan levere tal der er højere end rand()'s RAND_MAX?



Måske sådan en her:

int til_fendig(int nedre, int ovre)
{
    int rnd = rand() + rand();
    return (rnd%((ovre-nedre)+1)) + nedre;
}



OK... Det er vist på tide at jeg stopper med alle mine indlæg... LIGE NU... Bare lidt i det der humør lige nu :) hehe
Avatar billede arne_v Ekspert
02. november 2002 - 19:35 #9
Lidt afhængig af RNG'en og ens behov kan det sommetider
være en god ide at smide nogle af low bits væk (med
/ eller >>) inden modulus.
Avatar billede arne_v Ekspert
02. november 2002 - 19:39 #10
mbulow>

Selvfølgelig kan man lave RNG'ere som kan generere
vilkårligt stor tal.

En simple metode er at kombinere flere
RNG'ere.
Avatar billede anarchy Nybegynder
02. november 2002 - 20:10 #11
Ok, glad for at se I svarer, ser gerne lidt komentarer og forklaring, er stadig newbie her.

Og så enlig en funktion der kunne bruges mere end en gang igennem et program.
Avatar billede arne_v Ekspert
02. november 2002 - 20:18 #12
mbulow>

Man kan kombinere, men med *aldrig* med plus.

rand()+rand() er nemlig ikke uniformt fordelt !
Avatar billede arne_v Ekspert
02. november 2002 - 20:33 #13
Jeg skal måske lige forklare den sidste.

Lad os sige at rand() har fordelingen:
0 - 1/4
1 - 1/4
2 - 1/4
3 - 1/4
så vil rand()+rand() have fordelingen:
0 - 1/16
1 - 2/16
2 - 3/16
3 - 4/16
4 - 3/16
5 - 2/16
6 - 1/16
Avatar billede mbulow Nybegynder
02. november 2002 - 21:56 #14
arne_v > Nej selvfølgelig ikke... Ren tanketorsk fra min side :)

Jeg kiggede lige noget gammelt source igennem, hvor jeg lavede noget lignende, og der havde jeg da også selv brugt * (Heldigvis da)

Floooot mbulow... Læg 2^16 sammen med 2^16 og forvent at få 2^32. Der er da vist en del af min der ikke er helt vågen idag =) lol
Avatar billede arne_v Ekspert
02. november 2002 - 22:00 #15
Øh.

rand()*rand() er altså heller ikke uniformt fordelt.

Med 0-3 alle 1/4 giver det:
0 - 7/16
1 - 1/16
2 - 2/16
3 - 2/16
4 - 1/16
6 - 2/16
9 - 1/16
Avatar billede arne_v Ekspert
02. november 2002 - 22:02 #16
Men rand()*(RAND_MAX+1)+rand() har en chance !
Avatar billede anarchy Nybegynder
02. november 2002 - 22:18 #17
Hehe det er da meget godt at i kan hijack'e mit spm til jeres egen diskussion :)

Der skal også nok blive delt point ud, så snart en af jer hjælper mig ud her:

Kan jeg få en komenteret version af progget så jeg kan se hvordan det virker, ellers lærer jeg så intet.
Avatar billede mbulow Nybegynder
02. november 2002 - 23:32 #18
Hehe... Det har du helt ret i anarchy... Og det vil jeg da gerne undskylde stort for :) Det er sådan en kedelig evne jeg har en gang imellem... Lad mig se om jeg ikke kan rette lidt op på det :)


Soreno's kode:
--------------

#include <stdio.h>  //Giver bl.a. adgang til printf()
#include <stdlib.h>  //Giver bl.a. adgang til rand() og srand()
#include <time.h>    //Giver bl.a. adgang til time()

int til_feldig(int nedre, int ovre)
{
    //Det der bliver gjort her er:
    // 1) ovre-nedre
    //    Beregner forskellen mellem ovre og nedre.
    //    (Kalder lige resultatet af dette A)
    // 2) rand() % A
    //    rand() giver et tal mellem 0 og RAND_MAX (Defineret som 32767).
    //    % giver 'rest ved division', dvs rand() % A giver en værdi mellem
    //    0 og A-1.
    //    (Kalder lige resultatet af dette B)
    // 3) B + nedre
    //    Dette vil så give en værdi mellem nedre og ovre-1.
    //PS) Da JEG mener at det virker mere logisk at nedre og ovre, angiver
    //    henholdsvis det mindste og største tal som funktionen kan
    //    returnere, var den første af mine utallige kommentarer at det
    //    kunne opnås ved istedet at skrive:
    //    return (rand() % ((ovre-nedre)+1)) + nedre;

    return (rand()%(ovre-nedre))+nedre;
}

int main(int argc, char **argv)
{
    //Hvis ikke srand kaldes inden rand, vil rand generere den samme
    //række 'tilfældige' tal hver gang... Det gør det heller ikke bedre at
    //kalde srand med det samme tal hver gang, derfor bruges time(0) i
    //stedet for, så resultatet varierer fra gang til gang.
    srand(time(0));

    //Udskriv 20 forskellige 'tilfældige' tal mellem 1000 og 1010
    for(int i=0;i<20;i++)
    {
        printf("%i\n", til_feldig(1000, 1010));
    }
   
    return 0;
}



Jeg håber jeg har fået rettet lidt op på det rod jeg har lavet, og at du kan bruge mine kommentarer til noget... Det er efter min mening helt klart soreno der skal have point's for det her, da det er den mest rigtige løsning :)

Du kan sagtens bruge til_feldig lige så mange gange du har lyst gennem dit program, men du skal huske at kande srand(time(0)) først eller er der ikke meget tilfældighed over de tal du får...



PS!!! Til alle der har læst dette spørgsmål, og alle kommentarer/svar igennem... Glem lige alt det jeg har haft gang i her... Jeg tænker helt klart med den del jeg sidder på lige for tiden... Der er ikke ret meget logik i det jeg har skrevet, hvilket vist også er tydeligt nok :)
Avatar billede anarchy Nybegynder
02. november 2002 - 23:42 #19
Well Soreno får point'ene siden han smed functionen, ville gerne gi' dig point mbulow for din forklaring den er meget fyldest gørende.
Avatar billede mbulow Nybegynder
02. november 2002 - 23:45 #20
Det du dog skal være opmærksom på er at løsningen som den ser ud lige nu har et lille (måske stort) problem.

rand() returnerer som sagt en værdi mellem 0 og 32767. Dvs som til_feldig ser ud lige nu vil denne funktion max kunne returnere 32768 forskellige tal.

Hvis du f.eks. kalder til_feldig sådan her:
  til_feldig(100, 100000);
vil rand() % 99900 altid give værdien af rand().
Resultatet af til_fældig vil så altid ligge mellem 100+0 og 100+32767, altså aldrig komme i nærheden af 100000.

Derfor vil funktionen kun virke korrekt hvis 'ovre - nedre' er mindre end eller lig med 32767 (RAND_MAX)

Derfor var alle mine kommantarer, et håbløst forsøg på hurtigt at finde en god løsning på at få til_feldig til altid at returnere værdier fra nedre til ovre. Men der fejlede jeg vist håbløst, men hvis jeg nu ellers holder <beep> med alle mulige ugennemtænkte idéer kunne det jo være en af de andre havde en god idé.
Avatar billede mbulow Nybegynder
02. november 2002 - 23:46 #21
anarchy > Efter den gang forvirring jeg har skabt, ville jeg have det meget dårligt med mig selv hvis jeg modtog points for det, så det passer mig helt fint at soreno får dem :)
Avatar billede soreno Praktikant
02. november 2002 - 23:48 #22
arne skrev:
"Lidt afhængig af RNG'en og ens behov kan det sommetider
være en god ide at smide nogle af low bits væk (med
/ eller >>) inden modulus."

det tror jeg ikke helt jeg har forstået, kunne du ikke forklare det ?
Avatar billede arne_v Ekspert
03. november 2002 - 00:01 #23
De fleste RNG'er er LCG'er og de er notorisk
mindre random i low bits end i high bits.

Der er nogle hvor low bit skifter 1-0-1-0-1-0-...
og hvis man f.eks. bryger % 2 på den direkte, så
er det absolut ikke random.

Der er også nogle hvor low 2 bits skifter
00-11-10-01-00-11-10-01.

LCG og modulus med powers af 2 er farligt.

Derfor hvis man bruger en LCG RNG, og man skal
have relativt små tal så vil:
  (rand()>>b)%n
være mere sikkert end:
  rand()%n

Prøv evt. at skrive low 2 bits ud af din foretrukne
RNG en 10-20 gange.

Adskillige meget kendte algoritmer fra IBM, Borland
og Unix har problemet !
Avatar billede soreno Praktikant
03. november 2002 - 00:06 #24
mange tak for forklaringen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester