Rand5 () do Rand7 () [zamknięte]

29

Otrzymujesz funkcję Rand5 (). Ta funkcja zwraca idealnie losowe (równomiernie rozmieszczone) liczby całkowite od 1 do 5.

Podaj funkcję Rand7 (), która używa Rand5 () do tworzenia idealnie losowych liczb całkowitych od 1 do 7.

Dan McGrath
źródło
3
Duplikat pytania
Mateen Ulhaq
8
Obowiązkowe xkcd: xkcd.com/221
Steven Rumbalski
1 i 5 włącznie? tj. z zestawu {1,2,3,4,5}?
Aaron McDaid,
1
Jakie kryteria determinują pojedynczego zwycięzcę?
kojiro
Ten moment, kiedy zdajesz sobie sprawę, że to właściwie stare pytanie.
nyuszika7h,

Odpowiedzi:

11

Java - 61 znaków

int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}

Przetestuj sterownik do sprawdzania poprawności:

class Rand {

    public static void main(String[] args) {
        int[] nums = new int[7];
        // get a lot of numbers
        for(int i = 0; i < 10000000; i++) nums[rand7()-1]++;
        // print the results
        for(int i = 0; i < 7; i++) System.out.println((i+1) + ": " + nums[i]);
    }

    // just for rand5()
    static java.util.Random r = new java.util.Random();

    static int rand5() {
        return r.nextInt(5)+1; // Random.nextInt(n) returns 0..n-1, so add 1
    }

    static int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}

}

Wyniki

C:\Documents and Settings\glowcoder\My Documents>java Rand
1: 1429828
2: 1429347
3: 1428328
4: 1426486
5: 1426784
6: 1429853
7: 1429374

C:\Documents and Settings\glowcoder\My Documents>
corsiKa
źródło
10
Dodatkowe punkty za „idzie do operatora”
Steve P.
ogolić chara? int rand7 () {for (int s = 0, c = 7; c -> 0; s + = rand5 ()); return s% 7 + 1;}
Ron
3
Ta odpowiedź jest nieprawidłowa: prawdopodobieństwo tej funkcji zwracającej wartości od 1 do 7 wynosi odpowiednio 0,1430656, 0,1430016, 0,1428224, 0,1426432, 0,1426432, 0,1428224 i 0,143 0016. Tak, różnica między minimalnym i maksymalnym prawdopodobieństwem jest mniejsza niż 0,0005, ale wciąż w pytaniu określono „całkowicie losowe liczby całkowite”.
Ilmari Karonen
@ilmari Masz rację - właśnie przeprowadziłem test i wygląda na to, że dystrybucja nawet nie jest ... pomyślę o tym ...
corsiKa
1
@userunknown: Tak, prawdopodobieństwa, które podałem, w rzeczywistości nie są przybliżeniami, są one dokładne (0,1430656 = 11177/78125 itd.) przy założeniu, że są całkowicie losowe rand5. Przeliczyłem je w Maple przy użyciu prostej algebry macierzowej, ale możesz to zrobić ołówkiem i papierem w ciągu kilku minut, jeśli chcesz. W każdym razie okazuje się, że Omar opublikował już te same dane (bez współczynnika normalizującego) w komentarzu do innej odpowiedzi kilka dni wcześniej. (Również ps., Możesz @ tylko powiadomić jednego użytkownika na komentarz, chociaż autor wpisu jest zawsze powiadamiany zawsze.)
Ilmari Karonen
7

Perl - 47 (było 52) znaków

sub rand7{($x=5*&rand5+&rand5-3)<24?int($x/3):&rand7} 

Plus mogę użyć trójskładnikowego operatora ORAZ rekurencji. Najlepszy… dzień… kiedykolwiek!

OK, 47 znaków, jeśli używasz mod zamiast div:

sub rand7{($x=5*&rand5+&rand5)<27?$x%7+1:&rand7} 
bariera
źródło
Tak blisko ... zamień 30 na 27 (= 6 + 21), a otrzymasz idealnie równomierny rozkład. Aha, możesz upuścić dwa ostatnie &znaki, aby sprowadzić go do 46 znaków (w tym spacji, co oznacza, że ​​twoja obecna wersja to 48).
Ilmari Karonen,
7

JavaScript, 42

Rand7=f=_=>(x=Rand5()+Rand5()*5-5)>7?f():x

Dodatkowa rzecz ES5:

Rand7=eval.bind(0,'for(;x=Rand5()+Rand5()*5-5,x>7;);x')
Ry-
źródło
6

Ruby - 54 znaki (na podstawie rozwiązania Dana McGratha, przy użyciu pętli)

def rand7;x=8;while x>7 do x=rand5+5*rand5-5 end;x;end

Ruby - 45 znaków (to samo rozwiązanie, przy użyciu rekurencji)

def rand7;x=rand5+5*rand5-5;x>7 ?rand7: x;end
Eskat0n
źródło
Można go skrócić o 1 znak za pomocą (x=rand5+5*rand5-5)>7?.
Lars Haugseth,
5

W Pythonie:

def Rand7():
  while True:
    x = (Rand5() - 1) * 5 + (Rand5() - 1)
    if x < 21: return x/3 + 1
Alexandru
źródło
4

W Common Lisp 70 znaków:

(defun rand7()(let((n(-(+(rand5)(* 5(rand5)))5)))(if(> n 7)(rand7)n)))

Nawiasy zajmują więcej miejsca, niż bym chciał.

Jonathan Sternberg
źródło
Miły. Możesz wycisnąć dwie kolejne postacie, tworząc zmienną globalną na:(defun rand7()(setq n(-(+(rand5)(* 5(rand5)))5))(if(> n 7)(rand7)n))
Dr. Pain
Jeszcze lepiej:(defun rand7()(if(>(setq n(-(+(rand5)(* 5(rand5)))5))7)(rand7)n))
Dr. Pain
4

W c / c ++ przy użyciu próbkowania odrzucania

int rand7(){int x=8;while(x>7)x=rand5()+5*rand5()-5;return x;}

62 znaków.

Dan McGrath
źródło
@barrycarter: Warunek jest while(x>7)taki, że byłyby spełnione tylko liczby w prawidłowym zakresie.
mellamokb
Mój błąd. Usunąłem mój głupi komentarz.
barrycarter
@barry A potem zostawiłeś kolejny. ;)
Mateen Ulhaq
Kilka minut zajęło mi zrozumienie, w jaki sposób matematyka wytwarza równomiernie losowy rozkład, który można wykorzystać do prób odrzucenia.
Daniel
3

Tłumaczenie na PHP, z odpowiedzi opublikowanej przez Dana McGratha.

function Rand7(){$x=8;while($x>7)$x=rand5()+5*rand5()-5;return $x;}

67 znaków.

Marc-François
źródło
Czy nie powinno to być poprzedzone słowem „funkcja” (i spacja)?
jtjacques
Tak ... a teraz ma 67 znaków ...
Marc-François
3

R, 34 znaki

W języku R (język zbudowany do obliczeń statystycznych) celowo oszustwo:

# Construct a Rand5 function
Rand5 <- function() sample(seq(5),1)
# And the golf
Rand7=function(r=Rand5())sample(1:(r/r+6),1)
# Or (same character count)
Rand7=function(r=Rand5())sample.int(r/r+6,1)
# Or even shorter(thanks to @Spacedman)
Rand7=function()sample(7)[Rand5()]

Dzięki leniwej ocenie argumentów wyeliminowałem średnik i nawiasy klamrowe.

Wyjście ponad 10 ^ 6 powtórzeń:

> test <- replicate(10^6,Rand7())
> table(test)
test
     1      2      3      4      5      6      7 
142987 142547 143133 142719 142897 142869 142848 

library(ggplot2)
qplot(test)

histogram of results

Ari B. Friedman
źródło
2
Jeśli zamierzasz być oszustem, równie dobrze możesz być najlepszym oszustem, Rand7=function(){r=Rand5();sample(7)[r]}
jakim
Jeśli masz zamiar to zrobić, po co zawracać sobie głowę magazynem pośrednim? Rand7=function(){sample(7)[Rand5()]}
Brian Diggs,
@BrianDiggs Zależność od ścieżki w akcji .... :-)
Ari B. Friedman
3

scala, 47, 40 59 znaków:

def rand7:Int={val r=5*(rand5-1)+rand5
if(r<8)r else rand7}

z 2 wejściami z rand5:

\ 1 2 3 4 5 
1 1 2 3 4 5  
2 6 7 8 ..
3 11 ..
4 ..
5

Pomnożę pierwszy-1 przez 5 i dodam drugi. Większość wyników jest ignorowana i prowadzi do nowych obliczeń. Wynikiem powinna być równa dystrybucja wartości od 1 do 25, z których wybieram tylko 7 pierwszych. Mogłem zaakceptować pierwsze 21 z budowaniem modulo, ale doprowadziłoby to do dłuższego kodu.

historyczny kod, który zawiódł, ale niezbyt oczywiście. Dzięki Ilmari Karonen za zwrócenie na to uwagi:

def rand7=(1 to 7).map(_=>rand5).sum%7+1

Dzięki Yoshiteru Takeshicie za to podejście scala-2.8.0, dzięki któremu „suma” była tak łatwa. Moje rozwiązanie wcześniej:

def rand7=((0/:(1 to 7))((a,_)=>a+rand5-1))%7+1

rand5:

val rnd = util.Random 
def rand5 = rnd.nextInt (5) + 1

nieznany użytkownik
źródło
Użytkownik Yoshiteru Takeshita zaproponował redukcję do 40 znaków w Scali 2.8.0 lub nowszej jakodef rand7=(1 to 7).map(_=>rand5).sum%7+1
Peter Taylor
To rozwiązanie również nie jest poprawne, patrz komentarze do odpowiedzi glowcodera .
Ilmari Karonen,
@IlmariKaronen: Masz rację - przerobiłem swoje rozwiązanie.
użytkownik nieznany
3

C ++

int Rand4()
{
    int r = Rand5();
    return r > 4 ? Rand4() : r;
}

inline int Rand8()
{    
    return (Rand4() - 1) << 2 + Rand4();
}

int Rand7()
{
    int r = Rand8();
    return r > 7 ? Rand7() : r;
}

C ++ (109)

Grał w golfa

int Rand4(){int r=Rand5();return r>4?Rand4():r;}int Rand7(){int r=Rand4()-1<<2+Rand4();return r>7?Rand7():r;}
Mateen Ulhaq
źródło
Nie sądzę, że można nazwać to „linią pojedynczą”, ponieważ średniki definiują wiersz kodu w C ++.
Peter Olson
@Peter No cóż, nie wymaga już nawet jednego linera.
Mateen Ulhaq
Zwrócił
2

Tłumaczenie na Javascript, z odpowiedzi zamieszczonej przez Dana McGratha.

function Rand7(){x=8;while(x>7)x=rand5()+5*rand5()-5;return x}

62 znaki

Clyde Lobo
źródło
1
function Rand7(){for(x=8;x>7;x=rand5()+5*rand5()-5);return x}jest nieco krótszy: P
JiminP
2

JavaScript, 85

function Rand7(){for(x=0,i=1;i<8;x^=i*((k=Rand5())%2),i*=1+(k<5));return x?x:Rand7()}

Wiem, że odpowiedź jest krótsza, ale chciałem pokazać test tej układanki. Okazuje się, że tylko odpowiedź Clyde Lobo przy użyciu próbkowania odrzucenia Dana McGratha jest poprawna (między odpowiedziami JS).

JiminP
źródło
2

С ++

int Rand7()
{
    int r = Rand5();
    int n = 5;
    do {
        r = (r - 1) * 5 + Rand5();
        int m = n * 5 / 7 * 7;
        if (r <= m) {
            return r % 7 + 1;
        }
        r -= m;
        n = n * 5 - m;
    } while (1);
}

Rozkład liczb (1000000 liczb całkowitych):

142935 142751 142652 143299 142969 142691 142703

Średnia liczba wywołań do Rand5 () na każdą wygenerowaną liczbę całkowitą wynosi około 2,2 (od 2 do 10+).

1 2      3      4     5    6   7 8  9 10
0 840180 112222 44433 2212 886 0 60 6 1
Andreyul
źródło
2

W Javie (lub C / C ++, jak sądzę)

  • używając formuły generowania Alexandru, w 65 znakach:

    int rand7(){int x=rand5()*5+rand5()-6;return x>20?rand7():x/3+1;}
    
  • z wykorzystaniem formuły generacyjnej Dana McGratha, w 60 znakach

    int rand7(){int x=rand5()+5*rand5()-5;return x>7?rand7():x;}
    
jtjacques
źródło
1

Clojure - 58 znaków

(defn rand7[](#(if(<% 8)%(rand7))(+(rand5)(*(rand5)5)-5)))
mikera
źródło
1

Python, 56 37 znaków

Inne rozwiązanie, które może być niepoprawne, w Pythonie:

rand7 = lambda: sum(rand5() for i in range(7)) % 7 + 1

To wydaje się zbyt proste, ale kiedy próbuję:

counter = [0] * 7
for i in range(100000):
     counter[rand7()] += 1

Dostaję dość równomierną dystrybucję (wszystkie między 14000 a 14500).

Dobra, teraz, gdy ktoś głosował na ten post: Czy to rozwiązanie jest rzeczywiście poprawne? Bardziej opublikowałem to tutaj, aby ludzie go krytykowali. Cóż, jeśli jest to poprawne, moja wersja w golfa byłaby:

rand7=lambda:eval("+rand5()"*7)%7+1

który wychodzi na 37 znaków.

cemper93
źródło
Twoje rozwiązanie jest nieprawidłowe: decyzję podejmujesz na podstawie 7 rzutów rzetelnej 5-stronnej kości, co oznacza, że ​​możliwe jest uzyskanie 5 ^ 7 (od 5 do 7 potęgi) możliwych do uzyskania wyników. Ponieważ nie jest to wielokrotność liczby 7, nie można zwrócić 7 możliwych do uzyskania wyników. Nie sądzę, aby istniała prosta formuła zwrotu; możesz brutalnie wymusić obliczenia lub wypracować je ręcznie na mniejszych liczbach (przerzuć 3 monety (H = 1, T = 2) i zsumuj wyniki).
Gilles „SO- przestań być zły”
1
Wow, rozkład, który generujesz, choć nie jest jednolity, jest niezwykle bliski: dokładna proporcja prawdopodobieństw każdej liczby wynosi {1: 11177, 2: 11172, 3: 11158, 4: 11144, 5: 11144, 6: 11158, 7: 11172}
Omar,
1

Java, 65 znaków:

int rand7(){int r;do{r=rand5()+5*rand5()-5;}while(r>7);return r;}
Hans-Peter Störr
źródło
1

Python, 70 znaków

def rand7():
 while True:
  n=5*(rand5()-1)+(rand5()-1)
  if n<21:return n%7+1

ale całkowicie poprawne na podstawie uzasadnienia tutaj .

Michael Foukarakis
źródło
1

Perl, 43 znaki, iteracyjne próbkowanie odrzucenia

sub rand7{1while($_=5*&rand5-rand5)>6;$_+1}

Daje to ostrzeżenie Ambiguous use of -rand5 resolved as -&rand5(), ale działa poprawnie. Przygotowanie &również do drugiego rand5połączenia naprawia go kosztem jednego pociągnięcia. (I odwrotnie, drugi &można również usunąć, jeśli rand5 został zdefiniowany za pomocą() prototypu.)

Ps. Następująca 46-znakowa wersja jest około trzy razy szybsza:

sub rand7{1while($_=5*&rand5-rand5)>20;$_%7+1}
Ilmari Karonen
źródło
1

Java - 66 znaków

int rand7(){int s;while((s=rand5()*5+rand5())<10);return(s%7+1);}

Dłuższa niż poprzednia procedura, ale myślę, że ta zwraca równomiernie rozłożone liczby w krótszym czasie.

David Gonzales
źródło
1

PostScript (46)

Używa binarnego kodowania tokenów, dlatego oto zrzut heksowy:

00000000  2f 72 61 6e 64 37 7b 38  7b 92 38 37 92 61 7b 92  |/rand7{8{.87.a{.|
00000010  40 7d 69 66 92 75 32 7b  72 61 6e 64 35 7d 92 83  |@}if.u2{rand5}..|
00000020  35 92 6c 92 01 35 92 a9  7d 92 65 7d 92 33        |5.l..5..}.e}.3|
0000002e

Aby go wypróbować, możesz go również pobrać .

Oto niepoznany i skomentowany kod wraz z kodem testowym.

% This is the actual rand7 procedure.
/rand7{
  8{                      % potentialResult
    % only if the random number is less than or equal to 7, we're done
    dup 7 le{             % result
      exit                % result
    }if                   % potentialResult
    pop                   % -/-
    2{rand5}repeat        % randomNumber1 randomNumber2
    5 mul add 5 sub       % randomNumber1 + 5*randomNumber2 - 5 = potentialResult
  }loop
}def

%Now, some testing code.

% For testing, we use the built-in rand operator; 
% Doesn't really give a 100% even distribution as it returns numbers
% from 0 to 2^31-1, which is of course not divisible by 5.
/rand5 {
  rand 5 mod 1 add
}def

% For testing, we initialize a dict that counts the number of times any number
% has been returned. Of course, we start the count at 0 for every number.
<<1 1 7{0}for>>begin

% Now we're calling the function quite a number of times 
% and increment the counters accordingly.
1000000 {
  rand7 dup load 1 add def
}repeat

% Print the results
currentdict{
  2 array astore ==
}forall
Thomas W.
źródło
-1
int result = 0;

for (int i = 0; i++; i<7)
    if (((rand(5) + rand(5)) % 2) //check if odd
        result += 1;

return result + 1;
Platon
źródło
2
To nie zapewni jednolitego rozkładu. Spójrz na rozkład rand (5) + rand (5) w ponad 10000 iteracjach, aby zobaczyć, dlaczego
gnibbler
wynikiem może być dowolna liczba od 1 do 8 w kodzie ...
Omar
Ponadto, jak powiedział gnibbler, rozkład nie jest jednolity: (rand (5) + rand (5))% 2 jest tendencyjne w kierunku 0, daje 0 13 razy na każde 12 razy daje 1; tzn. prawdopodobieństwa są proporcjonalne do {0: 13, 1: 12}. Przy takim zapisie prawdopodobieństwa dla Twojej funkcji są proporcjonalne do {1: 62748517, 2: 405451956, 3: 1122790032, 4: 1727369280, 5: 1594494720, 6: 883104768, 7: 271724544, 8: 35831808} (dość mocno wypaczone w kierunku większe liczby). Lub, ustalając, aby pętla działała 6 razy, {1: 4826809, 2: 26733096, 3: 61691760, 4: 75928320, 5: 52565760, 6: 19408896, 7: 2985984}
Omar
-1

R (30 znaków)

Zdefiniuj rand7:

rand7=function(n)sample(7,n,T)

Ponieważ R zostało napisane z myślą o analizie statystycznej, to zadanie jest banalne, a ja korzystam z wbudowanej funkcji sample z zamiennikiem ustawionym na PRAWDA.

Przykładowe dane wyjściowe:

> rand7(20)
 [1] 4 3 6 1 2 4 3 2 3 2 5 1 4 6 4 2 4 6 6 1
> rand7(20)
 [1] 1 2 5 2 6 4 6 1 7 1 1 3 7 6 4 7 4 2 1 2
> rand7(20)
 [1] 6 7 1 3 3 1 5 4 3 4 2 1 5 4 4 4 7 7 1 5
Andrie
źródło
1
Mówi, że musisz użyć Rand5. Nie mówi jak, ale musisz go użyć ...
Spacedman
@Spacedman Tak, wyraźnie to zignorowałem. To jest wykorzystanie przez brak odniesienia.
Andrie
-1

Groovy

rand7={if(b==null)b=rand5();(b=(rand5()+b)%7+1)}

przykładowy rozkład na 35 000 iteracji:

[1:5030, 2:4909, 3:5017, 4:4942, 5:5118, 6:4956, 7:5028]

Czy to źle, że jest stanowy?

Armand
źródło
-1

Mathematica, 30

Rand7=Rand5[]~Sum~{7}~Mod~7+1&
Mr.Wizard
źródło
-1

Co powiesz na to?

int Rand7()
{
    return Rand5()+ Rand5()/2;
}
sree
źródło
Niezależnie od języka, czy jego /operator wykonuje matematykę całkowitą? Co stanie się z wynikami, jeśli wykona matematy dziesiętny, zmiennoprzecinkowy lub całkowity?
kojiro
Zakładając, że podział całkowitej funkcja ta ma następujący rozkład: [2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25]. Niezupełnie jednolity.
primo
primo ma rację. dodawanie liczb losowych na ogół zniekształca prawdopodobieństwa w kierunku wartości średnich.
gnibbler
-1

Java - 54

int m=0;int rand7(){return(m=m*5&-1>>>1|rand5())%7+1;}

Test dystrybucji: [1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]

Algorytm:

  • Zachowaj zmienną globalną
  • pomnóż przez 5, więc otrzymasz co najmniej 5 miejsc wolnych co najmniej znaczącym końcu
  • Obetnij bit znaku, aby był dodatni (nie jest konieczny, jeśli obsługiwane są liczby bez znaku)
  • Modulo 7 jest odpowiedzią

> Liczby nie są już wzajemnie nieskorelowane, ale indywidualnie całkowicie przypadkowe.

Mark Jeronimus
źródło
-1

Rubinowy (43 bajty)

def rand7;(0..7).reduce{|i|i+rand5}%7+1;end

Rozwiązanie cemper93 przeniesione do Ruby jest trzy bajty krótsze;) (34 bajty)

def rand7;eval("+rand5"*7)%7+1;end
AlexRath
źródło
-3

Kod C / C ++ kod podstawowy ma tylko jedną linię!

static unsigned int gi = 0;

int rand7()
{
    return (((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1;
}

//call this seed before rand7
//maybe it's not best seed, if yo have any good idea tell me please
//and thanks JiminP again, he remind me to do this
void srand7()
{
    int i, n = time(0);
    for (i = 0; i < n % 7; i++)
        rand7();
}

Srand7 () jest zalążkiem rand7, musi wywołać tę funkcję przed rand7, podobnie jak wywołanie srand przed randem w C.

Jest to bardzo dobre, ponieważ wywołuje rand () tylko jeden raz, i nie ma pętli, nie zużywa dodatkowych wspomnień.

Pozwól mi to wyjaśnić: rozważ tablicę liczb całkowitych o rozmiarze 5:

1st get one number from 1 2 3 4 5 by rand5
2nd get one number from 2 3 4 5 6
3rd get one number from 3 4 5 6 7
4th get one number from 4 5 6 7 1
5th get one number from 5 6 7 1 2
5th get one number from 6 7 1 2 3
7th get one number from 7 1 2 3 4

Mamy więc TABELĘ, każda z 1-7 pojawia się w niej 5 razy i ma wszystkie 35 liczb, więc prawdopodobieństwo każdej liczby wynosi 5/35 = 1/7. I następnym razem

8th get one number from 1 2 3 4 5
9th get one number from 2 3 4 5 6
......

Po wystarczającej liczbie razy możemy uzyskać równomierny rozkład 1-7.

Możemy więc przydzielić tablicę, aby przywrócić pięć elementów 1-7 za pomocą przesunięcia w lewo-w pętli i uzyskać za każdym razem jedną liczbę z rand5. Zamiast tego możemy wygenerować wszystkie siedem tablic wcześniej i używać ich cyklicznie. Kod jest również prosty, ma wiele krótkich kodów, które mogą to zrobić.

Ale możemy użyć właściwości operacji%, więc wiersze tabeli 1-7 są równoważne z (rand5 + i)% 7, to znaczy: a = rand ()% 5 + 1 to rand5 w języku C, b = gi ++ % 7 generuje wszystkie permutacje w powyższej tabeli, a 0–6 zastępuje 1–7 c = (a + b)% 7 + 1, generuje 1–7 równomiernie. Wreszcie mamy ten kod:

(((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1 

Ale nie możemy uzyskać 6 i 7 przy pierwszym wywołaniu, więc potrzebujemy zarodka, takiego jak srand dla rand w C / C ++, aby zmienić rozkład permutacji dla pierwszego oficjalnego połączenia.

Oto pełny kod do testowania:

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

static unsigned int gi = 0;

//a = rand() % 5 + 1 is rand5 in C language,
//b = gi++ % 7 generates all permutations,
//c = (a + b) % 7 + 1, generates 1 - 7 uniformly.
//Dont forget call srand7 before rand7
int rand7()
{
   return (((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1;
}

//call this seed before rand7
//maybe it's not best seed, if yo have any good idea tell me please
//and thanks JiminP again, he remind me to do this
void srand7()
{
    int i, n = time(0);
    for (i = 0; i < n % 7; i++)
        rand7();
}

void main(void)
{
    unsigned int result[10] = {0};
    int k;

    srand((unsigned int)time(0)); //initialize the seed for rand
    srand7() //initialize the rand7

    for (k = 0; k < 100000; k++)
        result[rand7() - 1]++;

    for (k = 0; k < 7; k++)
        printf("%d : %.05f\n", k + 1, (float)result[k]/100000);
}
Sean
źródło
„Przechodzi” „test”, ale to nie znaczy, że jest to dobra funkcja losowa. Czy mogę dostać 6lub 7zadzwonić raz ?
JiminP
Ale są dobre i złe rodzaje zbliżenia. A ten kod jest zły - ponieważ nie zapewnia jednolitej dystrybucji, gdy wywoływany jest tylko raz. Jeśli ktoś napisał coś podobnego int main(){if(rand7()==6) printf("Hello, world!");}, przybliżenie za pomocą pętli wyświetli „Witaj, świecie!” 1 na 7 razy, ale twój kod nie.
JiminP
dziękuję @JiminP! masz rację za 6,7 ​​za pierwszym razem. Potrzebuję zarodka do rozłożenia, zanim zadzwonię do rand7, ziarenka takie jak srand w C / C ++. poprawiłem swój kod i jeszcze raz dziękuję !!!
Sean
hm .... srand10 nie działa, ostatnie 3 cyfry nie mogą uzyskać pozycji 10, 20, 30 ... przepraszam @JiminP, ale jak to zmienić? myślę, że to jest nadzieja.
Sean
2
Różne wywołania tej funkcji nie są od siebie niezależne. Specyfikacja tutaj tego nie wymaga, ale zazwyczaj jest to oczekiwane od generatorów liczb losowych. W przeciwnym razie można powiedzieć, zwróć losowy jednolity numer za pierwszym razem, a w przyszłych połączeniach po prostu wróć (poprzednie + 1)% 7 ...
Omar