Avatar billede ferret Nybegynder
08. maj 2003 - 20:58 Der er 27 kommentarer og
1 løsning

Seeding af rand()

Ok, her er mit spm, jeg har skrevet en dice roller, mest fordi jeg glemte mine terninger da jeg flyttede, og så fordi jeg syntes det kunne være sjovt. Jeg bruger en funktion der kan outputte et tilfældigt tal mellem 1 og 10. Men mit problem er tallene er ikke tilfældige nok.

Jeg seeder med time(0), er der ikke en måde jeg kan gøre tallene mere tilfældige?
Avatar billede arne_v Ekspert
08. maj 2003 - 21:04 #1
Husker du kun at seede 1 gang ?

(det ødelægger rand totalt at seede for hver gang !)
Avatar billede arne_v Ekspert
08. maj 2003 - 21:05 #2
Men ellers er der *meget* bedre random generatorer end standard
C rand.

Personligt er jeg glad for flere af L'Ecuyers algoritmer.
Avatar billede arne_v Ekspert
08. maj 2003 - 21:08 #3
Hvis du bruger:
  rand() % 10
så kan du muligvis forbedre en smule ved:
  (rand() / 1000) % 10

[rand() er som del andre random generatorer mere tilfældige i
high bits end i low bits - det har stor betydning hvis man bruger
modulus af en potens af 2 - muligvis har det også betydning med 10]
Avatar billede olennert Nybegynder
08. maj 2003 - 22:33 #4
Der er også nogle algoritmer i Knuths Art of Computer Programming om hvordan man tager en kendt (dårlig) tilfældighedstalgenerator, og laver om til en god tilfældighedstalgenerator. Jeg har brugt dem i forbindelse med generering af kunstig hvid støj til digital billedbehandling.

Fremragende bog (eller rettere, bøger, der er tre bind). Også selvom man må leve med at der er søgealgoritmer optimeret efter hvor mange båndstationer du har til rådighed :-).
Avatar billede arne_v Ekspert
08. maj 2003 - 22:41 #5
Det er "shuffling" du hentyder til ikke ?
Avatar billede arne_v Ekspert
08. maj 2003 - 22:43 #6
Random generatorer er nok et af de områder hvor der er sket
rigtigt meget de sidste 15 år.
Avatar billede ferret Nybegynder
09. maj 2003 - 00:45 #7
Cool nok, det er meget godt i kan smide en masse navne i hovedet på mig :> Men jeg ser gerne eksembler eller links, ok? Og jeg er ikke lige frem hardcore programør, så gerne noget 'lite'stuff, matematikken i det behøver ikke at være simpel, bare koden.
Avatar billede arne_v Ekspert
09. maj 2003 - 07:18 #8
Der er en beskrivelse af nogle af de nyere algoritmer på:
  http://www.ugcs.caltech.edu/info/gsl/rng_8.html

Jeg har implementeret gsl_rng_mrg (L'Ecuyer m.fk. 1993) i C:

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

static unsigned long int seed[5];

void mysrand(unsigned long int ss[])
{
  seed[0]=ss[0];
  seed[1]=ss[1];
  seed[2]=ss[2];
  seed[3]=ss[3];
  seed[4]=ss[4];
  return;
}

unsigned long int myrand()
{
  unsigned long int res;
  int i;
  res=(107374182*seed[0]+104480*seed[4])%2147483647;
  seed[4]=seed[3];
  seed[3]=seed[2];
  seed[2]=seed[1];
  seed[1]=seed[0];
  seed[0]=res;
  return res;
}

int main(int argc,char *argv[])
{
  unsigned long int ss[5];
  int i;
  ss[0]=1234567;
  ss[1]=123;
  ss[2]=4444;
  ss[3]=987;
  ss[4]=12321;
  mysrand(ss);
  for(i=0;i<10;i++) {
      printf("%ld\n",myrand());
  }
  exit(0);
}
Avatar billede arne_v Ekspert
09. maj 2003 - 07:20 #9
Algoritmen har et meget godt ry.

Jeg håbr at min implementerng er korrekt (der er ikke mange
muligheder for at lave fejl).

Bemærk at seed er et array på 5 som alle skal initialiseres
med time(), clock(), IP address, whatever du nu kan finde på.
Avatar billede olennert Nybegynder
09. maj 2003 - 10:13 #10
arne_v> Jo, det er shuffling. Algorithm B, p. 32, The Art of Computer Programming Vol 2 Seminumerical Algorithms, Second Edition.
Avatar billede ferret Nybegynder
09. maj 2003 - 10:20 #11
Well det ser ud some om der er en fejl et eller andet sted, siden VC++ ikke gider at compile, jeg får bare en masse fejl:

--------------------Configuration: rand2 - Win32 Debug--------------------
Compiling...
4.cpp
d:\ny mappe\c\rand2\4.cpp(6) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(7) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(8) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(9) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(10) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(11) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(15) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(16) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(17) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(18) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(19) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(20) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(21) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(22) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(23) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(27) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(28) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(29) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(30) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(31) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(32) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(33) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(34) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(35) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(36) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(36) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(36) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(37) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(38) : error C2018: unknown character '0xa0'
d:\ny mappe\c\rand2\4.cpp(39) : warning C4508: 'main' : function should return a value; 'void' return type assumed
Error executing cl.exe.
Avatar billede ferret Nybegynder
09. maj 2003 - 10:21 #12
Det var dit eksembel BTW.
Avatar billede arne_v Ekspert
09. maj 2003 - 10:23 #13
Mystisk.

Der er ikke nogen 0xa0 i koden ??

Warning'en kan du slippe af med at erstatte
  exit(0);
med:
  return 0;
Avatar billede ferret Nybegynder
09. maj 2003 - 10:24 #14
Never mind, det ser ud som om der var en eller anden usynlig karater i starten af hver linie.
Avatar billede arne_v Ekspert
09. maj 2003 - 10:27 #15
Bemærk iøvrigt at også for denne algoritme gælder at man skal
kund srand'e en gang. Hvis man srand'er for hver kald til rand, så
ødelægger man det totalt. Ligesom for standard srand/rand.
Avatar billede arne_v Ekspert
09. maj 2003 - 10:28 #16
Nå.

OK - sommetider sker der ting når man flytter kode mellem
browser og IDE.
Avatar billede ferret Nybegynder
09. maj 2003 - 10:33 #17
Jeg fandt ud af det, du får point, bare lige et sidste spørgsmål, hvordan seeder man bedst funktionen?
Avatar billede ferret Nybegynder
09. maj 2003 - 10:35 #18
Mit program ser sådan her ud:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "Useful_func.h"

using namespace std;

int main()
{

  unsigned long int ss[5];
  ss[0]=time(0);
  ss[1]=5454758;
  ss[2]=545452;
  ss[3]=9807;
  ss[4]=24578;
  mysrand(ss);   
  int diff = 0;
  int dices = 0;
  int succ = 0;
  int roll = 0;
  int ones = 0;

  cout<<"Welcome to the WoD Dice roller!"<<endl
      <<"Please enter difficulty...:";
  cin>>diff;
  cout<<"...And number of dice:";
  cin>>dices;
 
  srand(time(0));

  for(int i = 1; i <= dices; i++)
  {
   
    roll = rand2(0,10);
   
    if(roll >= diff){
        cout<<i<<". roll: "<<roll<<"  Success!"<<endl;
        succ++;}
    if((roll < diff) && (roll !=1))
        cout<<i<<". roll: "<<roll<<" Failure."<<endl;
    if(roll == 1){
        cout<<i<<". roll: "<<roll<<" BOTCH!"<<endl;
        ones++;}
    }
   
        if((succ == 0) && (ones >= 1))
            cout<<"You botched, you had "<<ones<<" ones and "<<succ<<" successes."<<endl;
        else
            cout<<"You had: "<<succ<<" successes and "<<ones<<" ones."<<endl;
       
  system("PAUSE");   
  return 0;
}

Godt, eller nej?
Avatar billede ferret Nybegynder
09. maj 2003 - 10:36 #19
Argh bleh, glemte det her - myrand funktionen ligger i useful_func, of rand2 ser sådan her ud:

int rand2(int lower, int upper)
{
    return (myrand()%(upper-lower)+1)+lower;
}
Avatar billede arne_v Ekspert
09. maj 2003 - 10:40 #20
Det burde være OK.

Hvis programmet bliver startet 2 gange indenfor samme sekund, så
vil de to kørsler generere samme sekvens.

Men hvis programmet kun skal køre i en instans samtidigt er det ikke noget problem.
Avatar billede arne_v Ekspert
09. maj 2003 - 10:42 #21
Hvis du vil give den en tand til:

ss[0]=time(NULL); // tid siden 1. januar 1970
ss[1]=clock(); // CPU tid siden program start
ss[2]=getpid(); // process ID
ss[3]=9807;
ss[4]=24578;
Avatar billede arne_v Ekspert
09. maj 2003 - 10:44 #22
rand2 ser OK ud - man skal lige huske at rand2(0,10) kan returnere
11 forskellige værdier.
Avatar billede ferret Nybegynder
09. maj 2003 - 10:47 #23
Cool nok, men hvilken header fil ligger getpid() i?
Avatar billede arne_v Ekspert
09. maj 2003 - 11:02 #24
unistd.h på Posix compliant systemer (hvilket ca. er alle
non-Windows systemer).
Avatar billede ferret Nybegynder
09. maj 2003 - 11:02 #25
JA men nu er sagen jo at jeg sidder med en Win2k maskine :>
Avatar billede arne_v Ekspert
09. maj 2003 - 11:05 #26
Jeg prøver lige at finde ud af hvor den er på Windows.
Avatar billede ferret Nybegynder
09. maj 2003 - 11:06 #27
Takker, du får points nu :)
Avatar billede arne_v Ekspert
09. maj 2003 - 11:10 #28
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