Rand5 () bis Rand7 () [geschlossen]

29

Sie erhalten eine Funktion Rand5 (). Diese Funktion gibt vollkommen zufällige (gleichverteilte) Ganzzahlen zwischen 1 und 5 zurück.

Stellen Sie die Funktion Rand7 () bereit, die Rand5 () verwendet, um vollkommen zufällige Ganzzahlen zwischen 1 und 7 zu erzeugen.

Dan McGrath
quelle
3
Doppelte Frage
Mateen Ulhaq
8
Obligatorische xkcd: xkcd.com/221
Steven Rumbalski
1 und 5 inklusive? dh aus der Menge {1,2,3,4,5}?
Aaron McDaid
1
Welche Kriterien bestimmen einen einzelnen Gewinner?
Kojiro
Dieser Moment, in dem Sie erkennen, dass dies tatsächlich eine alte Frage ist.
nyuszika7h

Antworten:

11

Java - 61 Zeichen

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

Testfahrer zur Validierung:

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;}

}

Ergebnisse

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
quelle
10
Extra-Punkte für die "geht an Betreiber"
Steve P
einen char rasieren? int rand7 () {für (int s = 0, c = 7; c -> 0; s + = rand5 ()); Rückgabe von s% 7 + 1;}
Ron
3
Diese Antwort ist nicht korrekt: Die Wahrscheinlichkeiten für diese Funktion, die die Werte von 1 bis 7 zurückgibt, sind 0,1430656, 0,1430016, 0,1428224, 0,1426432, 0,1426432, 0,1428224 bzw. 0,1430016. Ja, der Unterschied zwischen der minimalen und der maximalen Wahrscheinlichkeit ist kleiner als 0,0005, aber die Frage spezifizierte immer noch "perfekt zufällige ganze Zahlen".
Ilmari Karonen
@ilmari Du hast recht - ich habe gerade einen Test durchgeführt und es scheint, dass die Verteilung nicht einmal ... lass mich darüber nachdenken ...
corsiKa
1
@userunknown: Ja, die Wahrscheinlichkeiten, die ich gepostet habe, sind eigentlich keine Näherungswerte. Sie sind exakt (0,1430656 = 11177/78125 usw.) und gehen von einem vollkommen zufälligen Wert aus rand5. Ich habe sie in Maple mit einfacher Matrixalgebra berechnet, aber Sie können es mit Bleistift und Papier in ein paar Minuten tun, wenn Sie wollen. Wie auch immer, Omar hat die gleichen Zahlen (ohne Normalisierungsfaktor) bereits ein paar Tage zuvor in einem Kommentar zu einer anderen Antwort veröffentlicht . (Auch ps., Sie können nur einen Benutzer pro Kommentar @notifizieren, obwohl der Autor des Beitrags in jedem Fall benachrichtigt wird.)
Ilmari Karonen
7

Perl - 47 (war 52) Zeichen

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

Außerdem kann ich den ternären Operator AND recursion verwenden. Bester Tag überhaupt!

OK, 47 Zeichen, wenn du mod anstelle von div verwendest:

sub rand7{($x=5*&rand5+&rand5)<27?$x%7+1:&rand7} 
barrycarter
quelle
Schließen Sie also ... ersetzen Sie die 30 durch 27 (= 6 + 21) und Sie erhalten eine perfekt gleichmäßige Verteilung. Oh, und Sie können die letzten beiden &Zeichen fallen lassen, um 46 Zeichen zu erhalten (einschließlich des Leerzeichens, das Ihre aktuelle Version auf 48 setzt).
Ilmari Karonen
7

JavaScript, 42

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

Bonus ES5 Sache:

Rand7=eval.bind(0,'for(;x=Rand5()+Rand5()*5-5,x>7;);x')
Ry-
quelle
6

Ruby - 54 Zeichen (basierend auf der Dan McGrath-Lösung, unter Verwendung einer Schleife)

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

Ruby - 45 Zeichen (gleiche Lösung mit Rekursion)

def rand7;x=rand5+5*rand5-5;x>7 ?rand7: x;end
Eskat0n
quelle
Kann mit um 1 Zeichen gekürzt werden (x=rand5+5*rand5-5)>7?.
Lars Haugseth
5

In Python:

def Rand7():
  while True:
    x = (Rand5() - 1) * 5 + (Rand5() - 1)
    if x < 21: return x/3 + 1
Alexandru
quelle
4

In Common Lisp 70 Zeichen:

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

Die Klammern nehmen mehr Platz ein, als ich möchte.

Jonathan Sternberg
quelle
Nett. Sie können zwei weitere Zeichen auspressen, indem Sie eine globale Variable festlegen:(defun rand7()(setq n(-(+(rand5)(* 5(rand5)))5))(if(> n 7)(rand7)n))
Dr. Pain
Noch besser:(defun rand7()(if(>(setq n(-(+(rand5)(* 5(rand5)))5))7)(rand7)n))
Dr. Pain
4

In C / C ++ unter Verwendung Verwerfungsmethode

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

62 Zeichen.

Dan McGrath
quelle
@barrycarter: Die Bedingung ist while(x>7), so dass nur Zahlen im gültigen Bereich genügen würden.
Mellamokb
Mein Fehler. Löschte meinen dummen Kommentar.
Barrycarter
@barry Und dann hast du noch einen hinterlassen. ;)
Mateen Ulhaq
Ich brauchte ein paar Minuten, um zu erkennen, wie die Mathematik hier eine gleichmäßig zufällige Verteilung erzeugt, die für die Rückweisungsabtastung verwendet werden kann.
Daniel
3

Übersetzung nach PHP, aus der Antwort von Dan McGrath.

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

67 Zeichen.

Marc-François
quelle
Sollte dem nicht das Wort "function" (und ein Leerzeichen) vorangestellt werden?
Jtjacques
Ja ... und jetzt sind es 67 Zeichen ...
Marc-François
3

R, 34 Zeichen

In R (eine Sprache, die für statistische Berechnungen entwickelt wurde) eine bewusst betrügerische Lösung:

# 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()]

Dank der faulen Auswertung der Argumente habe ich das Semikolon und die geschweiften Klammern entfernt.

Ausgabe über 10 ^ 6 Wiederholungen:

> 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)

Histogramm der Ergebnisse

Ari B. Friedman
quelle
2
Wenn Sie betrügerisch sein werden, können Sie auch der beste Betrüger sein, den Sie sein können:Rand7=function(){r=Rand5();sample(7)[r]}
Spacedman
Wenn Sie das tun werden, warum sollten Sie sich um die Zwischenlagerung kümmern? Rand7=function(){sample(7)[Rand5()]}
Brian Diggs
@ BrianDiggs Pfadabhängigkeit in Aktion .... :-)
Ari B. Friedman
3

scala, 47, 40 59 Zeichen:

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

mit 2 Eingängen von rand5:

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

Ich multipliziere die erste 1 mit 5 und addiere die zweite. Die meisten Ergebnisse werden ignoriert und führen zu einer neuen Berechnung. Das Ergebnis sollte eine gleichmäßige Verteilung der Werte von 1-25 sein, von denen ich nur die ersten 7 auswähle. Ich könnte die ersten 21 mit einem Modulo akzeptieren, aber das würde zu längerem Code führen.

historischer Code, der fehlgeschlagen ist, aber nicht sehr offensichtlich. Vielen Dank an Ilmari Karonen für den Hinweis:

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

Vielen Dank an Yoshiteru Takeshita für diesen Scala-2.8.0-Ansatz, der 'sum' so einfach gemacht hat. Meine Lösung vor:

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

rand5:

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

Benutzer unbekannt
quelle
Benutzer Yoshiteru Takeshita schlug eine Reduzierung auf 40 Zeichen für Scala 2.8.0 oder höher alsdef rand7=(1 to 7).map(_=>rand5).sum%7+1
Peter Taylor
Diese Lösung ist auch nicht korrekt, siehe die Kommentare zur Antwort von glowcoder .
Ilmari Karonen
@IlmariKaronen: Sie haben Recht - ich habe meine Lösung überarbeitet.
Benutzer unbekannt
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)

Golf gespielt

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
quelle
Ich glaube nicht, dass man das als "Einzeiler" bezeichnen kann, da Semikolons eine Codezeile in C ++ definieren.
Peter Olson
@Peter Na ja, es werden nicht einmal mehr Einzeiler benötigt.
Mateen Ulhaq
Es gab eine Zahl von 1 bis 8 zurück.
jimmy23013
2

Übersetzung in Javascript aus der Antwort von Dan McGrath.

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

62 Zeichen

Clyde Lobo
quelle
1
function Rand7(){for(x=8;x>7;x=rand5()+5*rand5()-5);return x}ist etwas kürzer: 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()}

Ich weiß, es gibt eine kürzere Antwort, aber ich wollte den Test dieses Puzzles zeigen. Es stellt sich heraus, dass nur Clyde Lobos Antwort unter Verwendung von Dan McGraths Ablehnungsstichprobe korrekt ist (zwischen JS-Antworten).

JiminP
quelle
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);
}

Zahlenverteilung (1000000 Ganzzahlen):

142935 142751 142652 143299 142969 142691 142703

Die durchschnittliche Anzahl der Aufrufe von Rand5 () pro generierter Ganzzahl beträgt ungefähr 2,2 (2 bis 10+).

1 2      3      4     5    6   7 8  9 10
0 840180 112222 44433 2212 886 0 60 6 1
Andreyul
quelle
2

In Java (oder C / C ++, nehme ich an)

  • unter Verwendung der Generationsformel von Alexandru in 65 Zeichen:

    int rand7(){int x=rand5()*5+rand5()-6;return x>20?rand7():x/3+1;}
    
  • unter Verwendung der Generationsformel von Dan McGrath in 60 Zeichen

    int rand7(){int x=rand5()+5*rand5()-5;return x>7?rand7():x;}
    
jtjacques
quelle
1

Clojure - 58 Zeichen

(defn rand7[](#(if(<% 8)%(rand7))(+(rand5)(*(rand5)5)-5)))
mikera
quelle
1

Python, 56 37 Zeichen

Eine andere Lösung, die in Python falsch sein kann:

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

Dies scheint zu einfach zu sein, aber wenn ich versuche:

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

Ich bekomme eine einigermaßen gleichmäßige Verteilung (alle zwischen 14000 und 14500).

Okay, jetzt, als jemand für diesen Beitrag gestimmt hat: Ist diese Lösung in der Tat richtig? Ich habe das hier mehr gepostet, um die Leute dazu zu bringen, es zu kritisieren. Nun, wenn es richtig ist, wäre meine Golfversion:

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

Das ergibt 37 Zeichen.

cemper93
quelle
Ihre Lösung ist nicht korrekt: Sie stützen Ihre Entscheidung auf 7 Würfe eines fairen 5-seitigen Würfels, was bedeutet, dass es 5 ^ 7 (5 bis zur 7. Potenz) gleich wahrscheinliche Ergebnisse gibt. Da dies kein Vielfaches von 7 ist, können Sie keine 7 gleichwahrscheinlichen Ergebnisse zurückgeben. Ich glaube nicht, dass es eine einfache Formel für Ihre Rückkehr gibt. Sie können die Berechnung brachial erzwingen oder sie von Hand auf kleineren Zahlen berechnen (3 Münzen umdrehen (H = 1, T = 2) und die Ergebnisse summieren).
Gilles 'SO - hör auf, böse zu sein'
1
Wow, die Verteilung, die Sie generieren, ist bemerkenswert ähnlich, obwohl sie nicht einheitlich ist: Der genaue Anteil der Wahrscheinlichkeiten jeder Zahl beträgt {1: 11177, 2: 11172, 3: 11158, 4: 11144, 5: 11144, 6: 11158, 7: 11172}
Omar,
1

Java, 65 Zeichen:

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

Python, 70 Zeichen

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

aber völlig richtig aufgrund der Begründung hier .

Michael Foukarakis
quelle
1

Perl, 43 Zeichen, iterative Ablehnungsabtastung

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

Dies gibt eine Warnung über Ambiguous use of -rand5 resolved as -&rand5(), funktioniert aber korrekt. Wenn Sie einen Anruf &auch auf den zweiten rand5Anruf vorbereiten , wird der Fehler auf einen Schlag behoben . (Umgekehrt kann der andere &auch entfernt werden, wenn rand5 er mit einem ()Prototyp definiert wurde .)

Ps. Die folgende 46-Zeichen-Version ist ungefähr dreimal schneller:

sub rand7{1while($_=5*&rand5-rand5)>20;$_%7+1}
Ilmari Karonen
quelle
1

Java - 66 Zeichen

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

Länger als die vorherige Routine, aber ich denke, diese gibt gleichmäßig verteilte Zahlen in kürzerer Zeit zurück.

David Gonzales
quelle
1

PostScript (46)

Dies verwendet eine binäre Token-Codierung. Daher hier ein Hexdump:

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

Zum Ausprobieren können Sie es auch herunterladen .

Hier ist der unbenutzte und kommentierte Code zusammen mit dem Testcode.

% 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.
quelle
-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
quelle
2
Dies ergibt keine gleichmäßige Verteilung. Schauen Sie sich die Verteilung von rand (5) + rand (5) über 10000 Iterationen an, um
herauszufinden,
Ergebnis kann eine beliebige Zahl von 1 bis 8 in Ihrem Code sein ...
Omar
Außerdem ist die Verteilung, wie der Gnibbler sagte, nicht einheitlich: (rand (5) + rand (5))% 2 ist in Richtung 0 vorgespannt, es erzeugt 0 13-mal für jedes 12-mal, das es 1 erzeugt; dh die Wahrscheinlichkeiten sind proportional zu {0: 13, 1: 12}. Mit dieser Notation sind die Wahrscheinlichkeiten für Ihre Funktion proportional zu {1: 62748517, 2: 405451956, 3: 1122790032, 4: 1727369280, 5: 1594494720, 6: 883104768, 7: 271724544, 8: 35831808} (ziemlich stark verzerrt in Richtung größere Zahlen). Oder Sie korrigieren die Schleife so, dass sie sechsmal ausgeführt wird: {1: 4826809, 2: 26733096, 3: 61691760, 4: 75928320, 5: 52565760, 6: 19408896, 7: 2985984}
Omar,
-1

R (30 Zeichen)

Rand7 definieren:

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

Da R mit Blick auf statistische Analysen geschrieben wurde, ist diese Aufgabe trivial und ich benutze die eingebaute Funktion sample Ersetzung auf TRUE gesetzt ist.

Beispielausgabe:

> 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
quelle
1
Es heißt, Sie müssen Rand5 verwenden. Sagt nicht wie, aber du musst es benutzen ...
Spacedman
@Spacedman Ja, ich habe es explizit ignoriert. Das wird durch Nichtbezug verwendet.
Andrie
-1

Groovy

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

Beispielverteilung über 35.000 Iterationen:

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

Ist es schlimm, dass es stateful ist?

Armand
quelle
-1

Mathematica, 30

Rand7=Rand5[]~Sum~{7}~Mod~7+1&
Mr.Wizard
quelle
-1

Wie wäre es damit?

int Rand7()
{
    return Rand5()+ Rand5()/2;
}
sree
quelle
Welche Sprache auch immer ist, macht ihr /Operator Ganzzahlen-Mathematik? Was passiert mit Ihren Ergebnissen, wenn es sich um Dezimal-, Gleitkomma- oder Ganzzahl-Mathematik handelt?
Kojiro
Unter der Annahme , ganzzahlige Division, hat diese Funktion die folgende Verteilung: [2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25]. Nicht gerade einheitlich.
Primo
Primo ist richtig. Das Hinzufügen von Zufallszahlen führt im Allgemeinen zu einer Verschiebung der Wahrscheinlichkeiten in Richtung der mittleren Werte.
Gnibbler
-1

Java - 54

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

Verteilungstest: [1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]

Algorithmus:

  • Behalten Sie eine globale Variable
  • multiplizieren Sie mit 5, so dass am niedrigstwertigen Ende 5 Plätze frei sind
  • Kürzen Sie das Vorzeichenbit, um es positiv zu machen (nicht erforderlich, wenn vorzeichenlose Zahlen unterstützt werden).
  • Modulo 7 ist die Antwort

> Die Zahlen sind nicht mehr unkorreliert, sondern einzeln perfekt zufällig.

Mark Jeronimus
quelle
-1

Ruby (43 Bytes)

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

Die auf Ruby portierte Lösung von cemper93 ist drei Bytes kürzer;) (34 Bytes)

def rand7;eval("+rand5"*7)%7+1;end
AlexRath
quelle
-3

C / C ++ - Code Der Kerncode besteht nur aus einer Zeile!

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();
}

Das srand7 () ist der Same von rand7, muss diese Funktion vor rand7 aufrufen, genauso wie das Aufrufen von srand vor rand in C.

Dies ist eine sehr gute Methode, da sie rand () nur einmal aufruft und keine Schleife, keine zusätzlichen Speicher benötigt.

Lassen Sie es mich erklären: Betrachten Sie ein ganzzahliges Array mit der Größe 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

Also haben wir die TABELLE, jede von 1-7 erscheint fünfmal darin und hat alle 35 Zahlen, also ist die Wahrscheinlichkeit für jede Zahl 5/35 = 1/7. Und das nächste Mal,

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

Nach einiger Zeit können wir die gleichmäßige Verteilung von 1-7 erhalten.

Also können wir ein Array zuweisen, um die fünf Elemente von 1-7 durch Verschieben von links nach links wiederherzustellen, und jedes Mal eine Zahl von dem Array von rand5 erhalten. Stattdessen können wir alle sieben Arrays zuvor generieren und sie zirkulär verwenden. Der Code ist auch einfach, hat viele Kurzcodes, die das können.

Wir können jedoch die Eigenschaften von% operation verwenden, sodass die Zeilen in Tabelle 1-7 (rand5 + i)% 7 entsprechen, dh: a = rand ()% 5 + 1 ist rand5 in C-Sprache, b = gi ++ % 7 erzeugt alle Permutationen in der obigen Tabelle und 0 - 6 ersetzen 1 - 7 c = (a + b)% 7 + 1, erzeugt 1 - 7 gleichmäßig. Endlich haben wir diesen Code:

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

Wir können jedoch beim ersten Aufruf nicht 6 und 7 erhalten, daher benötigen wir einen Startwert, z. B. srand für rand in C / C ++, um die Permutation für den ersten formalen Aufruf zu ändern.

Hier ist der vollständige Code zum Testen:

#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
quelle
Es 'besteht' den 'Test', aber das heißt nicht, dass dies eine gute Zufallsfunktion ist. Kann ich es bekommen 6oder einmal7 anrufen ?
5.
Aber es gibt gute und schlechte Arten der Annäherung. Und dieser Code ist schlecht - weil er bei nur einmaligem Aufruf keine gleichmäßige Verteilung ergibt. Wenn man so etwas schreibt int main(){if(rand7()==6) printf("Hello, world!");}, gibt die Annäherung mit der Schleife "Hallo Welt!" 1 in 7 mal, aber Ihr Code nicht.
5.
danke @JiminP! Sie sind für 6,7 zum ersten Mal richtig. Ich brauche einen Startwert, um vor dem Aufruf von rand7 die Reihenfolge zu ändern. Ich habe meinen Code gefixt und nochmals vielen Dank !!!
Sean
hm .... der srand10 funktioniert nicht, die letzten 3 nummern können nicht an 10, 20, 30 ... positionen kommen. sorry @JiminP, aber wie kann ich das ändern? Ich denke, das ist ein hoffnungsvoller Weg.
Sean
2
Unterschiedliche Aufrufe dieser Funktion sind nicht unabhängig voneinander. Die Spezifikation hier erfordert dies nicht, aber das wird normalerweise von Zufallszahlengeneratoren erwartet. Andernfalls können Sie sagen, dass Sie beim ersten Mal eine zufällige einheitliche Zahl zurückgeben und bei zukünftigen Aufrufen einfach (vorherige + 1)% 7 ...
Omar,