Generiere eine beliebige ganze Zahl

17

Ihr Programm / Funktion sollte

  • gibt genau eine ganze Zahl aus
  • Gibt eine beliebige Ganzzahl mit positiver Wahrscheinlichkeit aus
  • Geben Sie eine ganze Zahl größer als 1.000.000 oder kleiner als -1.000.000 mit einer Wahrscheinlichkeit von mindestens 50% aus.

Beispielausgaben (alle müssen möglich sein):

59875669123
12
-42
-4640055890
0
2014
12
24
-7190464664658648640055894646646586486400558904644646646586486400558904646649001

Klarstellungen:

  • Ein abschließender Zeilenumbruch ist zulässig.
  • Führende Nullen sind nicht erlaubt.
  • -0 ist erlaubt.

Kürzester Code gewinnt.

randomra
quelle
2
@Optimizer warum nimmst du eine einheitliche Wahrscheinlichkeit an? Die Frage gibt es nicht. Tatsächlich scheint es von diesem Punkt an klar zu sein, dass die Verteilung nicht gleichmäßig sein muss, solange mindestens 50% außerhalb von [-1 Millionen, 1 Million] liegen.
Hobbs
10
Eine Lösung, die eine " gleichmäßige Verteilung über alle ganzen Zahlen" erzeugt, ist unmöglich. Da es unendlich viele Ganzzahlen gibt, würde jede einzelne Ganzzahl mit einer Wahrscheinlichkeit von 0 erscheinen. (Oder: Die Ausgabe einer endlichen Zahl würde bedeuten, dass Sie unendlich viele andere vernachlässigen!) Jede Lösung muss höhere Werte ablehnen, um P (gesamt) zu erhalten ) = 1.
Joeytwiddle
2
@Ypnypn Der Arbeitsspeicher des Computers ist ebenfalls nicht begrenzt. Sie müssen Ihre Teilleistung nirgendwo speichern.
Jimmy23013
4
@GiantTree - way too long to fit in an integer- Dies gilt nur, wenn Sie davon ausgehen, dass integerdies der intDatentyp in einem 32/64-Bit-Bogen ist, was nicht unbedingt eine gültige Annahme ist. "Integer" wurde als mathematischer Ausdruck gestartet , für den keine Größenbeschränkungen gelten.
Fake Name
5
Jeder, der einen Pseudozufallszahlengenerator verwendet, um seine Entscheidungen für die Ausgabe zu treffen, schließt fast alle Ganzzahlen aus und begrenzt die Größe der zu erzeugenden Ganzzahlen nach oben (vorausgesetzt, der PRNG hat eine endliche Periode). Kann dies bei Antworten außer Acht gelassen werden oder erfordert eine gültige Antwort einen echten Zufallszahlengenerator?
Trichoplax

Antworten:

12

CJam, 16 14 13 Bytes

0{Kmr(+esmr}g

Dies dauert sehr lange, da der aktuelle Zeitstempel (in der Größenordnung von 10 bis 12 ) verwendet wird, um zu bestimmen, ob die Schleife beendet werden soll. Ich verwende dies als Vorlage, da es die kürzeste ist, aber es gibt zwei 14-Byte-Alternativen, die ihre eigenen Vorzüge haben:

0{esmr(+esmr}g

Dieser ist nicht durch den Zeitraum des PRNG begrenzt, da der Bereich aller Zufallszahlen vom aktuellen Zeitstempel abhängt. Daher sollte dies in der Lage sein, eine beliebige Zahl zu erzeugen, obwohl die Wahrscheinlichkeit für negative oder sogar kleine positive Zahlen verschwindend gering ist.

Unten finden Sie eine entsprechende Version, die 3e5anstelle des Zeitstempels verwendet wird. Und 20für den ersten Bereich (als 13-Byte-Übermittlung). Es ist viel schneller und entspricht auch allen Regeln. Es ist eine Art Grenzfall, die 50% -Wahrscheinlichkeit für Zahlen über 1.000.000 zu erhalten, während eine angemessene Laufzeit und eine kleine Codegröße beibehalten werden. Die Erklärung und mathematische Begründung beziehen sich auf diese Version:

0{Kmr(+3e5mr}g

Dies dauert normalerweise einige Sekunden. Sie können das 5durch ein ersetzen 2, damit es noch schneller läuft. Dann wird die Anforderung an die 50% -Wahrscheinlichkeit jedoch nur für 1.000 statt 1.000.000 erfüllt.

Ich fange bei 0 an. Dann habe ich eine Schleife, aus der ich mit Wahrscheinlichkeit 1 / (3 * 10 5 ) ausbreche . Innerhalb dieser Schleife füge ich meiner laufenden Summe eine zufällige ganze Zahl zwischen -1 und 18 (einschließlich) hinzu. Es gibt eine begrenzte (wenn auch geringe) Wahrscheinlichkeit, dass jede Ganzzahl ausgegeben wird, wobei positive Ganzzahlen viel wahrscheinlicher sind als negative (ich glaube nicht, dass Sie in Ihrem Leben eine negative sehen werden). Wenn Sie mit einer so geringen Wahrscheinlichkeit ausbrechen und die meiste Zeit inkrementieren (und viel mehr addieren als subtrahieren), werden Sie in der Regel über 1.000.000 hinausgehen.

0              "Push a 0.";
 {          }g "Do while...";
  Kmr          "Get a random integer in 0..19.";
     (         "Decrement to give -1..18.";
      +        "Add.";
       3e5mr   "Get a random integer in 0..299,999. Aborts if this is 0.";

Eine mathematische Begründung:

  • In jedem Schritt addieren wir durchschnittlich 8,5.
  • Um auf 1.000.000 zu kommen, benötigen wir 117.647 dieser Schritte.
  • Die Wahrscheinlichkeit, dass wir weniger als diese Anzahl von Schritten machen, ist

    sum(n=0..117,646) (299,999/300,000)^n * 1/300,000
    

    die auswertet zu 0.324402. Daher werden wir in etwa zwei Dritteln der Fälle mehr als 117.647 Schritte ausführen, und zwar jeweils 1.000.000.

  • (Beachten Sie, dass dies nicht die exakte Wahrscheinlichkeit ist, da es einige Schwankungen bei diesen Durchschnittswerten von 8,5 geben wird. Um jedoch auf 50% zu kommen, müssen wir deutlich über 117.646 hinausgehen und ungefähr 210.000 Schritte erreichen.)
  • Im Zweifelsfall können wir den Nenner der Abbruchwahrscheinlichkeit leicht in die Luft sprengen, bis zu, 9e9ohne irgendwelche Bytes hinzuzufügen (aber Jahre Laufzeit).

... oder 11 Bytes?

Schließlich gibt es eine 11-Byte-Version, die auch nicht durch die PRNG-Zeit begrenzt ist, sondern die jedes Mal so gut wie keinen Speicher mehr hat. Es wird nur eine Zufallszahl (basierend auf dem Zeitstempel) pro Iteration generiert und sowohl zum Inkrementieren als auch zum Beenden verwendet. Die Ergebnisse jeder Iteration verbleiben auf dem Stapel und werden erst am Ende aufsummiert. Vielen Dank an Dennis für diese Idee:

{esmr(}h]:+
Martin Ender
quelle
Ich habe der Frage einen Kommentar hinzugefügt, um zu sehen, ob die Regeln einen echten Zufallszahlengenerator erfordern, aber ich nehme an, dass Sie die Pedanterie schätzen würden. Ist Ihre Zufallsquelle hier pseudozufällig? Das würde die Menge der möglichen Ausgaben auf höchstens den Zeitraum Ihres PRNG beschränken, oder?
Trichoplax
(+1 unabhängig von der einfachen Eleganz)
Trichoplax
Ja, ich vermute alles soweit. Ich bin gespannt, ob jemand eine Antwort ohne dieses Problem veröffentlicht ...
trichoplax
Ich sehe, das OP hat festgestellt, dass Sie davon ausgehen können, dass Ihr Zufallszahlengenerator ein echter Zufallszahlengenerator ist, egal ob er es ist oder nicht - das ist jetzt überflüssig ... :)
Trichoplax
Die Summe Kmrin einer Periode ist wahrscheinlich immer eine große positive Zahl, die größer als die Periode ist. Und in diesem Fall kann nicht jede mögliche Zahl erzeugt werden.
Jimmy23013
11

Java, 133, 149

void f(){String s=x(2)<1?"-":"";for(s+=x(9)+1;x(50)>0;s+=x(10));System.out.print(x(9)<1?0:s);}int x(int i){return new java.util.Random().nextInt(i);}

Beispielausgaben

-8288612864831065123773
0
660850844164689214
-92190983694570102879284616600593698307556468079819964903404819
3264

Ungolfed

void f() {
    String s = x(2)<1 ? "-" : "";       // start with optional negative sign
    s+=x(9)+1;                          // add a random non-zero digit
    for(; x(50)>0; )                    // with a 98% probability...
        s+=x(10)                        // append a random digit
    System.out.print(x(9)<1 ? 0 : s);   // 10% chance of printing 0 instead
}

int x(int i) {
    return new java.util.Random().nextInt(i);
}

Alte Antwort (vor Regeländerung)

void f(){if(Math.random()<.5)System.out.print('-');do System.out.print(new java.util.Random().nextInt(10));while(Math.random()>.02);}
Ypnypn
quelle
Sie beide haben Recht, aber die Frage besagt, dass die Wahrscheinlichkeit mindestens 50% betragen muss, nicht im Bereich von +/- 1.000.000
GiantTree
@Optimizer Redone.
Ypnypn
Wenn Sie Binärliterale verwenden, müssen Sie das nicht drucken -.
TheNumberOne
4

Mathematica - 47

Round@RandomVariate@NormalDistribution[0,15*^5]

Generieren Sie einfach eine Zufallszahl unter Verwendung der Normalverteilung mit einer Varianz von 1500000. Dies ergibt eine ganze Zahl zwischen -10 ^ 6 und 10 ^ 6 mit einer Wahrscheinlichkeit von 49,5015%.

Swish
quelle
"Dies ergibt eine ganze Zahl zwischen -10 ^ 6 und 10 ^ 6 mit einer Wahrscheinlichkeit von 50,4985%." - das ist nicht genug. Haben Sie die Spezifikation falsch gelesen? Vielleicht wollten Sie 10 ^ 7 als Varianz verwenden?
John Dvorak
@ JanDvorak Falsche Wahrscheinlichkeit, sorry. Jetzt ist es das richtige.
Swish
Umfasst die Implementierung in Mathematica wirklich alle ganzen Zahlen? Ich habe keinen Zugriff auf die Quelle, aber ich würde nicht raten ...
Trichoplax
@githubphagocyte Es würde von der aktuellen Präzision abhängen.
Swish
4
Was ich damit meine ist, dass die Angabe einer bestimmten Genauigkeit Zahlen ausschließt, die größer sind als diese. Die einzige Möglichkeit besteht darin, eine unbegrenzte Genauigkeit anzugeben.
Trichoplax
4

Python 2, 75 69 Bytes

from random import*;s=0;j=randrange
while j(12):s=s*9+j(-8,9)
print s

Es ist trivial zu prüfen, ob die while-Schleife in der Mitte alle ganzen Zahlen erzeugen kann (wenn auch in Richtung Null voreingenommen). "12" wird so gewählt, dass ungefähr die Hälfte der Zahlen ± 10 6 überschreitet .


Ältere Lösung:

Python 2, 44 Bytes

Basierend auf der Mathematica-Lösung .

from random import*;print int(gauss(0,8**7))

Funktioniert nicht wirklich, da Pythons floatnur endliche Präzision hat.

kennytm
quelle
Dies wird nicht in der Lage sein, alle ganzen Zahlen zu erzeugen, da der Pseudozufallszahlengenerator eine endliche Menge an internen Zuständen hat. Laut der Dokumentation verwendet Python den Mersenne Twister, der Zustand ist also ziemlich groß. Es ist jedoch nicht unendlich, so dass es nur eine endliche Teilmenge aller ganzen Zahlen erzeugen kann.
Starblue
@starblue: Aus dem OP: "Sie können davon ausgehen, dass der Zufallszahlengenerator Ihrer Sprache ein echter Zufallszahlengenerator ist, auch wenn dies nicht der Fall ist."
Kennytm
3

Rubin, 70

f=->{m=10**6
r=rand -m..m
r<1?(r>-5e5??-:'')+r.to_s+f[][/\d+/]:r.to_s}

Um die Erzeugung sehr großer Zahlen zu ermöglichen, gebe ich die Zahl als eine Stringvon einem Lambda zurück. Wenn dies nicht zulässig ist, zählen Sie 8 zusätzliche Zeichen (für puts f[]), um es zu einem Programm anstelle einer Funktion zu machen.

Erläuterung

Generiere eine Zahl zwischen -1,000,000und 1,000,000. Wenn die Zahl 1größer oder gleich ist, wird die Zahl als a zurückgegeben String.

Ist die Zahl kleiner als 1, wird die Funktion rekursiv aufgerufen, um eine Zahl außerhalb des Nummernkreises zurückzugeben. Um sicherzustellen, dass auch negative Zahlen generiert werden können, -wird dem Ergebnis ein vorangestellt, Stringwenn die Anfangszahl größer als ist -500,000.

Ich hoffe ich habe die Herausforderung richtig verstanden!

britishtea
quelle
3

R 38

library(Rmpfr)
round(rnorm(1,2e6,1e6))

Ziehungen aus der Gaußschen Verteilung mit einem zufällig ausgewählten Mittelwert von 2.000.000 und einer Standardabweichung von 1.000.000, sodass etwa 2/3 der Ziehungen innerhalb von 1.000.000 und 3.000.000 liegen. Die Verteilung ist unbegrenzt, so dass theoretisch jede beliebige ganze Zahl generiert werden kann. Das Rmpfr-Paket ersetzt Rs eingebaute Doppelschwimmer mit beliebiger Genauigkeit.

Shadowtalker
quelle
Ja, ich habe gemerkt, dass ich die Spezifikation falsch verstanden habe. Und ich stelle mir vor, es hat die gleichen Einschränkungen für die Maschinengenauigkeit mit Mathematica
shadowtalker
Hmm, in diesem Fall bin ich mir nicht sicher. Ich werde mich darum kümmern müssen; Betrachten Sie diese Antwort als "auf Eis"
Shadowtalker
@ MartinBüttner behoben, denke ich
Shadowtalker
Interessant. Ich glaube nicht, dass Sie das ganze sample(c(1,-1),1)überlegen müssen. Nur um 1e6 zu zentrieren sollte ausreichen.
Martin Ender
@ MartinBüttner oh muss es nicht an beiden enden 50% sein? Das war nicht klar
shadowtalker
2

Perl, 53 Zeichen

print"-"if rand>.5;do{print int rand 10}while rand>.1

Ich sehe keinen Grund, mit ganzen Zahlen zu arbeiten, wenn ich eine drucke :)

Hat die gleiche Wahrscheinlichkeit, eine Zahl mit oder ohne vorangestelltem "-" zu drucken.

Druckt 10% der Zeit eine 1-stellige Zahl, 9% der Zeit eine 2-stellige Zahl, 8,1% der Zeit eine 3-stellige Zahl, 7,29% der Zeit eine 4-stellige Zahl und 5-stellige Zahl 6,56% der Zeit, eine 6-stellige Zahl 5,9% der Zeit usw. Jede Länge ist mit abnehmender Wahrscheinlichkeit möglich. Die Zahlen mit einer bis fünf Ziffern machen ungefähr 41,5% der Ausgabefälle aus, und die Zahl 1.000.000 (oder -1.000.000) macht nur 6-millionstel Prozent aus, so dass die Ausgabezahl außerhalb des Bereichs von -1.000.000 bis 1.000.000 bei 54,6 liegt % der ganzen Zeit.

Sowohl "0" als auch "-0" sind mögliche Ausgaben, von denen ich hoffe, dass sie kein Problem sind.

hobbs
quelle
Gibt das nicht "Zahlen" wie -00000000167 aus? Das ist nicht wirklich eine ganze Zahl.
Isaacg
1
@isaacg Ich verstehe nicht, warum das keine ganze Zahl ist.
Optimierer
2
@Optimizer Es ist, aber das OP hat Führende 0 ausdrücklich verboten.
Martin Ender
Sie können vor der Schleife eine zufällige führende Ziffer ungleich Null von -9 bis +9 generieren. print int(rand(20)-10)||1. Ich brauche eine Möglichkeit, um 0 als Ausgabe zu generieren. Vielleicht || stirb 0, wenn der nachfolgende Müll nach der Null erlaubt ist. Andernfalls brauchen Sie einen kurzen Weg, um die Null zu drucken und ohne weitere Ausgabe zu beenden, wenn int(rand(20)-10)==0.
Peter Cordes
@PeterCordes stimmte zu, das ist ein anständiger Ansatz, aber ich habe keine Lust, ihn zu schreiben, und ich denke nicht, dass er in Bezug auf die Länge wettbewerbsfähig wäre. Fühlen Sie sich frei, es auf eigene Faust einzureichen :)
Hobbs
2

Perl, 114 Zeichen

use Math::BigInt;sub r{$x=Math::BigInt->new(0);while(rand(99)!=0){$x->badd(rand(2**99)-2**98);}print($x->bstr());}

Nervenzusammenbruch:

use Math::BigInt;               -- include BigIntegers
  sub r{                        -- Define subroutine "r"
    $x=Math::BigInt->new(0);    -- Create BigInteger $x with initial value "0"
      while(rand(99)!=0){       -- Loop around until rand(99) equals "0" (may be a long time)
        $x->badd(               -- Add a value to that BigInt
          rand(2**99)-2**98);   -- Generate a random number between -2^98 and +2^98-1
        }print($x->bstr());}    -- print the value of the BigInt

Die Wahrscheinlichkeit, einen Wert zwischen -1.000.000 und 1.000.000 zu erhalten, tendiert gegen Null, ABER es ist möglich.

Hinweis: Diese Unterroutine wird möglicherweise längere Zeit ausgeführt und zeigt den Fehler "Out of Memory!" Fehler, aber es wird technisch eine beliebige Ganzzahl wie in der Frage angegeben generiert .

Perl, 25

sub r{rand(2**99)-2**98;}

Erzeugt eine zufällige Ganzzahl im Bereich von +/- 2 ^ 99.

Nervenzusammenbruch

sub r{                    -- Define subroutine "r"
     rand(2**99)          -- Generate a random integer between 0 and 2^99
                -2**98;}  -- Subtract 2^98 to get negative values as well

Getestet mit 1 Million Proben:

~5 are inside the range of +/-1.000.000
~999.995 are outside that range
= a probability of ~99,99% of generating an integer outside that range.
Compare that number to the probability of 2.000.000 in 2^99: It is approx. the same.

Dies erfüllt alle Regeln:

  • 1 ganze Zahl
  • jede ganze Zahl ist möglich
  • Mindestens 50% (in meinem Fall 99,99%) aller generierten Ganzzahlen liegen außerhalb des Bereichs von +/- 1.000.000.

Dies funktioniert, weil der zugrunde liegende Zufallszahlengenerator für jedes Bit, das generiert wird, die gleiche Wahrscheinlichkeit definiert. Dies gilt auch für generierte Ganzzahlen.
Jede ganze Zahl hat eine Wahrscheinlichkeit von 1/2 ^ 99, generiert zu werden.

Bearbeiten:

Ich musste den Exponenten erhöhen, damit größere ganze Zahlen generiert werden. Ich habe 99 gewählt, weil der Code so kurz wie möglich ist.

GiantTree
quelle
Sind wir uns nicht einig, dass es keine oberen / unteren Grenzen geben sollte? Beispielsweise hat die Ganzzahl 2 ^ 31 + 1 eine Wahrscheinlichkeit von 0, was gegen Regel 2
Optimierer
@Optimizer Für mich ist eine Ganzzahl wie in vielen Programmiersprachen definiert: eine Zahl innerhalb der Grenzen von -2^31und +2^31-1(32 Bit). Sie können die Exponenten leicht erhöhen, wenn Sie größere Ganzzahlen generieren möchten, dies kann jedoch je nach Implementierung von Perl fehlschlagen.
GiantTree
Ich habe gerade gesehen, dass auch diese lächerlich große ganze Zahl generiert werden muss. Ich werde meinen Code schnell bearbeiten.
GiantTree
@ MartinBüttner Ich habe mein Bestes versucht, um die Spezifikation der Frage zu erfüllen. Es ist mir einfach nicht möglich (zumindest nicht ohne Hilfe) unendlich große ganze Zahlen zu generieren. Perls größte Ganzzahl ist ungefähr 1.7e308, eine Grenze, die ich nicht kontrollieren kann.
GiantTree
@ MartinBüttner Beides ist aber zB möglich. Die Zeichenfolge würde nach 2 GB Daten überlaufen, sodass sie wieder endlich ist. Es ist schwer zu sagen, dass eine Zahl unendlich groß sein sollte, wenn es Probleme mit dem Speicher gibt. Bald werde ich mit BigInts einen anderen Ansatz finden. Außerdem läuft die Ganzzahl bei 1.7e308 nicht über und wird nur in infite konvertiert ( 1.#INFum genau zu sein)
GiantTree
2

C #, 126 107 Bytes

string F(){var a=new System.Random();var b=a.Next(-1E6,1E6+1)+"";while(a.Next(1)>0)b+=a.Next(10);return b;}

Ungolfed:

string F()
{
    System.Random rand = new System.Random();
    string rtn = rand.Next(-1E6, 1E6 + 1) + "";
    while (rand.Next(1) > 0)
         rtn += a.Next(10);
    return rtn;
}

Die Wahrscheinlichkeit, eine Anzahl von n Ziffern zu generieren , ist 1/2 ^ (n-10), was für alle positiven n größer als 0 ist, und 1/2 für n = 11.Erstellt auch führende Nullen, die in der ursprünglichen Frage oder einem ihrer Kommentare nicht unzulässig zu sein scheinen.

LegionMammal978
quelle
Bei der Verwendung using System;brauchen Sie nicht System.Randomzweimal, sondern nur Random, richtig?
Charlie
@Charlie Dies ist eine Funktion, daher kann ich keine usingAnweisungen verwenden. Es würde sowieso nur 1 Zeichen sparen.
LegionMammal978
1
Sie können 1 Zeichen sparen, indem Sie das Leerzeichen unter entfernen -1E6, 1E6+1.
ProgramFOX
2

Perl, 62 Bytes

print $n=int rand(20)-10;while($n&&rand>.1){print int rand 10}

Ich hatte die gleiche Idee wie @Hobbs, eine Ziffer nach der anderen zu generieren, aber sein Code erfüllte nicht die Anforderung, keine führenden Nullen zu setzen. Das Erzeugen der ersten Ziffer anstelle nur des Vorzeichens löste das. Und es sei denn, es gibt einen kürzeren Weg zum Beenden, wenn wir eine Null gedruckt haben, oder einen kürzeren Weg zum Generieren der führenden -9 bis 9, sollte dies für die Größe der Fall sein.

In einer Shell-Schleife: while perl -e '...'; do echo;done |less

Ich denke, dies ist eine der kürzesten, die nicht unendlich RAM benötigt, um das Problem zu lösen. Als Bonus ist die Ausgabe nicht stark auf irgendetwas ausgerichtet, und die Laufzeit ist sehr schnell.

Ich habe versucht, bitweise zu verwenden und ein Zeichen in der while-Bedingung zu speichern, aber ich denke, dass dies häufiger zutrifft, sodass die Schleife früher endet. Wäre mehr Zeichen erforderlich, um andere Dinge anzupassen, um dem entgegenzuwirken, um die Wahrscheinlichkeit für die Erzeugung von abs (Output)> 1M beizubehalten.

Peter Cordes
quelle
Schön, dass du ein paar Dinge herausgedrückt hast, an die ich nicht gedacht hätte :)
hobbs
1

Javascript (73)

Diese Lösung verwendet, dass Sie eine Zahl mit der Basis n konstruieren können, indem Sie die vorherige Zahl mit n multiplizieren und eine Ziffer zur Basis n hinzufügen . Wir haben ein zusätzliches ..?..:..Element, um alle negativen Ganzzahlen erstellen zu können. Der folgende Code sollte in einer Browserkonsole getestet werden.

b=Math.round;c=Math.random;x=0;while(b(c()*99)){x*=b(c())?2:-2;x+=b(c())}

Die Wahrscheinlichkeit, eine Ganzzahl> = 2^1(oder <= -(2^1)) zu erhalten, entspricht der Wahrscheinlichkeit, dass die Schleife zweimal ausgeführt wird. Die Chance dafür ist (98/99)^2. Die Chance, eine Zahl zu erhalten, die größer als 2^20(oder <= -(2^20)) ist, beträgt daher (98/99)^21 = 0.808oder 81%. Dies ist jedoch alles in der Theorie und unter der Annahme, dass Math.random wirklich zufällig ist. Es ist offensichtlich nicht.


Snippet, das diesen Code testet. Auch lesbarer.

Sumurai8
quelle
1
Das OP hat nun bestätigt, dass Sie davon ausgehen können, dass Ihr PRNG wirklich zufällig ist, auch wenn dies nicht der Fall ist.
Trichoplax
1

GolfScript, 20 Bytes

0{)8.?rand}do.2&(*4/

Ja, dieser ist auch ein bisschen langsam.

Im Vergleich zu Sprachen wie CJam und Pyth leidet GolfScript unter einem wortreichen Schlüsselwort zur Erzeugung von Zufallszahlen ( rand). Um dieses Handicap zu überwinden, musste ich einen Weg finden, es nur einmal zu benutzen.

Bei diesem Code wird wiederholt eine Zufallszahl zwischen 0 und 8 8 -1 = einschließlich 16.777.215 ausgewählt und ein Zähler inkrementiert, bis die Zufallszahl zufällig 0 ist. Der resultierende Zählerwert hat eine geometrische Verteilung mit einem Median von ungefähr -1 / log 2 (1 - 1/8 8 ) ≈ 11.629.080, so dass der Test "über 1.000.000 mindestens 50% der Zeit" erfüllt wird.

Leider ist die so erzeugte Zufallszahl immer streng positiv. Daher wird der zusätzliche .2&(*4/Teil benötigt, damit er negativ oder null wird. Es funktioniert, indem es das zweitniedrigste Bit der Zahl extrahiert (was entweder 0 oder 2 ist), es dekrementiert, um es zu -1 oder 1 zu machen, es mit der ursprünglichen Zahl multipliziert und das Ergebnis durch 4 dividiert (um es loszuwerden) die niedrigsten zwei Bits, die jetzt mit dem Vorzeichen korreliert sind, und auch, damit das Ergebnis Null wird). Auch nach der Division durch 4 hat der Absolutwert der Zufallszahl noch einen Median von -1 / log 2 (1 - 1/8 8 ) / 4 ≈ 2.907.270, sodass er den 50% -Test weiterhin besteht.

Ilmari Karonen
quelle
1

JavaScript, 81 Byte

Dieser Code erfüllt alle Regeln:

  • Gibt eine beliebige Ganzzahl mit positiver Wahrscheinlichkeit aus
  • Ganzzahlen außerhalb des Bereichs von +/- 1000000 mit einer Wahrscheinlichkeit von mindestens 50% ausgeben
  • Keine führenden 0in der Ausgabe

Als Bonus wird der Algorithmus mit einer Zeitkomplexität von O (log 10 n) ausgeführt, sodass die Ganzzahl fast sofort zurückgegeben wird.

for(s="",r=Math.random;r()>.1;s+=10*r()|0);r(s=s.replace(/^0*/,"")||0)<.5?"-"+s:s

Dies setzt eine REPL-Umgebung voraus. Versuchen Sie, den obigen Code in der Konsole Ihres Browsers auszuführen, oder verwenden Sie das folgende Stack-Snippet:

D.onclick = function() {
  for(s="", r=Math.random;r()>.1; s+=10*r()|0);
  P.innerHTML += (r(s=s.replace(/^0*/,"") || 0) <.5 ?"-" + s : s) + "<br>"
}
<button id=D>Generate a random number</button><pre id=P></pre>

Algorithmus :

  • Fügen Sie der Zeichenfolge weitere zufällige Ziffern hinzu, sbis a Math.random() > 0.1.
  • Basierend auf Math.random() > 0.5machen Sie die Zahl negativ (indem Sie den String smit voranstellen -).

Dieser Algorithmus hat keine einheitliche Verteilung über alle ganzen Zahlen. Ganzzahlen mit einer höheren Stellenzahl sind weniger wahrscheinlich als die niedrigeren. In jeder for-Schleifeniteration besteht eine 10% ige Chance, dass ich bei der aktuellen Ziffer anhalte. Ich muss nur sicherstellen, dass ich in mehr als 50% der Fälle nach 6 Ziffern aufhöre.

Diese Gleichung von @nutki erklärt den Maximalwert des Prozentsatzes der Stopp-Chance basierend auf der obigen Bedingung:

1 - 50%^(1/6) ≈ 0.11

Somit ist 0,1 in einem guten Bereich, um alle drei Regeln der Frage zu erfüllen.

Optimierer
quelle
Es gibt ein paar Dinge, die mich an dieser Antwort verwirren. Haben Sie angenommen, dass Math.random () eine gleichmäßige Verteilung von Zufallszahlen generiert, da die Spezifikation angibt, dass es implementierungsabhängig ist. Unter der Annahme, dass es sich um eine gleichmäßige Verteilung handelt, ist P (Math.random ()> 0,1) = 0,9, sodass eine große Wahrscheinlichkeit besteht, dass sie zwischen den einzelnen Iterationen endet. Eine Implementierung Ihres unter Firefox 34.0 Ubuntu ausgeführten Algorithmus gibt mir bei jedem Test eine Wahrscheinlichkeit von ~ 0,47 (<0,5): jsfiddle.net/WK_of_Angmar/dh8gq4pb
Wk_of_Angmar
Wie haben Sie es auch geschafft, eine zeitliche Komplexität für einen Algorithmus ohne Eingabe zu berechnen?
Wk_of_Angmar
1

TI-BASIC, 14 Bytes

1-2int(2rand:randNorm(AnsE6,9

Ähnlich wie bei der R-Antwort von @ ssdecontrol ergibt sich dies aus der Gaußschen Verteilung mit einem zufällig gewählten Mittelwert von -1.000.000 oder 1.000.000 und der Standardabweichung 9. Die Verteilung ist unbegrenzt, sodass theoretisch jede ganze Zahl generiert werden kann.

Erklärung :

1-2int(2rand     - get a random integer 0 or 1, then multiply by 2 and subtract 1
:                - this gives the number 1 or -1 (with equal probability) to Ans
randNorm(AnsE6,9 - displays Gaussian distribution with mean (Ans * 1,000,000) and std. dev. 9
Timtech
quelle
Aber kann es "2" oder "-2" erzeugen?
Kennytm
Ja offensichtlich. tibasicdev.wikidot.com/randnorm
Timtech
1
OK, lesen Sie den Code falsch (Gedanke :bedeutet "Drucken" aufgrund der Darstellung der Erklärung). Aber kann es Zahlen mit mehr als 20 Stellen erzeugen?
Kennytm
Als Ausgabe ist jede beliebige lange Ganzzahl möglich? Ist dies nicht durch die Reichweite von begrenzt randNorm?
Optimierer
"Die Verteilung ist unbegrenzt, so dass theoretisch jede beliebige Ganzzahl generiert werden kann." Es gibt keine Reichweite.
Timtech
1

Bash, 66

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/random

Fast immer wird 5000000 gedruckt. Wenn jedoch eine gültige Nummer in gefunden wurde /dev/random, wird diese Nummer stattdessen gedruckt.

Und dieser ist schneller:

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/urandom
jimmy23013
quelle
1
@Optimizer Es soll langsam sein. Das liegt daran, dass es sich um eine echte Zufallsquelle handelt. Aber du kannst es testen, mit /dev/urandomdem es weniger zufällig ist.
Jimmy23013
@Optimizer Wie wäre das mit manuellen Eingaben? Es liest eine Datei, aber alles ist eine Datei.
Nit
@Optimizer Ich verstehe einfach nicht, welchen Punkt Sie anstreben.
Nit
Das Lesen /dev/urandomin einem Shell-Skript ist im Grunde dasselbe wie das Aufrufen rand()in anderen Sprachen. Obwohl, wenn Sie wirklich bash verwenden, nicht POSIX sh, können Sie Zufallszahlen von erhalten echo $RANDOM. wiki.ubuntu.com/DashAsBinSh gibt hexdump /dev/urandomals Äquivalent für das absolute POSIX-Minimum an /bin/dash.
Peter Cordes
1

C ++, 95 Bytes

void f(){int d=-18,s=-1;while(s<9){d=(rand()%19+d+9)%10;cout<<d;s=9-rand()%10*min(d*d+s+1,1);}}

Erweitert:

void f() {
    int d=-18,s=-1;
    while(s<9) {
        d=(rand()%19+d+9)%10;
        cout<<d;
        s=9-rand()%10*min(d*d+s+1,1);
    }
}

Erläuterung:

Die Funktion druckt so lange aufeinanderfolgende zufällige Ziffern, bis ein Schalter mit zufälligen Werten den zum Stoppen der Funktion erforderlichen Wert annimmt. d ist die Variable, die den Wert der nächsten zu druckenden Ziffer beibehält. s ist die Schaltvariable, die im Intervall [0, 9] ganzzahlige Zufallswerte annimmt. Wenn s == 9, werden keine Ziffern mehr gedruckt und die Funktion endet.

Die Variablen d und s werden initialisiert, um der ersten Ziffer eine besondere Behandlung zu geben (sie wird aus dem Intervall [-9, 9] entnommen, und wenn die erste Ziffer Null ist, muss die Funktion beendet werden, um führende Nullen zu vermeiden). Der Wert von d könnte als d = rand ()% 10 zugewiesen werden, aber dann könnte die erste Ziffer nicht negativ sein. d wird stattdessen als d = (rand ()% 19 + d + 9)% 10 zugewiesen und bei -18 initialisiert, sodass der erste Wert von d zwischen [-9, 9] und der nächste Wert immer zwischen [0] liegt 9].

Die Variable s reicht zufällig von [0, 9], und wenn s gleich 9 ist, endet die Funktion. Nach dem Ausdruck der ersten Ziffer wird die nächste mit einer Wahrscheinlichkeit von 90% ausgegeben (vorausgesetzt, rand () ist wirklich zufällig, und um die dritte Bedingung zu erfüllen). s könnte leicht als s = rand ()% 10 zugewiesen werden. Es gibt jedoch eine Ausnahme: Wenn die erste Ziffer Null ist, muss die Funktion enden. Um eine solche Ausnahme zu behandeln, wurde s als s = 9-rand ()% 10 * min (d * d + s + 1,1) zugewiesen und als -1 initialisiert. Wenn die erste Ziffer Null ist, gibt das min 0 zurück und s entspricht 9-0 = 9. Die Zuweisung der Variablen reicht immer von [0, 9], sodass die Ausnahme nur bei der ersten Ziffer auftreten kann.

Merkmale (unter der Annahme, dass rand () wirklich zufällig ist)

  • Die Ganzzahl wird ziffernweise mit einer festen Wahrscheinlichkeit von 90% für das Drucken einer weiteren Ziffer nach dem Drucken der letzten Ziffer gedruckt.

  • 0 ist die Ganzzahl mit der höchsten Wahrscheinlichkeit, gedruckt zu werden, mit einer Wahrscheinlichkeit von ungefähr 5,2%.

  • Die Wahrscheinlichkeit, eine ganze Zahl im Intervall [-10 ^ 6, 10 ^ 6] zu drucken, beträgt ungefähr 44% (die Berechnung wird hier nicht geschrieben).

  • Positive und negative Ganzzahlen werden mit der gleichen Wahrscheinlichkeit gedruckt (~ 47,4%).

  • Nicht alle Ziffern werden mit der gleichen Wahrscheinlichkeit gedruckt. Beispiel: Wenn in der Mitte der Ausgabe der Ganzzahl die letzte Ziffer 5 war, hat die Ziffer 3 eine etwas geringere Chance, als nächstes gedruckt zu werden. Wenn die letzte Ziffer d war, hat die Ziffer (d + 18)% 10 im Allgemeinen eine etwas geringere Chance, als nächstes gedruckt zu werden.

Beispielausgaben (10 Ausführungen)

-548856139437
7358950092214
507
912709491283845942316784
-68
-6
-87614261
0
-5139524
7

Process returned 0 (0x0)   execution time : 0.928 s
Press any key to continue.
Daniel Turizo
quelle
1

Bash, 42 Bytes

printf "%d\n" 0x$(xxd -p -l5 /dev/random)
/ dev / random unter OSX besteht nur aus zufälligen Bytes und xxd -p -l5konvertiert 5 der ASCII-Zeichen in hexadezimal und wandelt printfsie in ein Dezimalformat um.

Camden
quelle
0

Pyth , 11 Bytes

WOyG~ZtOT)Z

Hinweis: Dieses Programm stürzt wahrscheinlich mit einem Speicherfehler auf einem realen Computer ab. Versuchen Sie zum Testen, durch Geine kürzere Zeichenfolge zu ersetzen , z. B. in diesem Code, der Zahlen mit einem Durchschnitt von etwa 28000 generiert:

pyth -c 'WOy"abcdefghijklm"~ZtOUT)Z'

Dieser Code durchläuft eine Schleife und addiert eine Zufallszahl von -1 bis 8 Zmit einer Wahrscheinlichkeit von 2 ^ -26, die Schleife bei jeder Wiederholung zu verlassen. Die 2 ^ -26 Wahrscheinlichkeit wird durch Auswahl eines zufälligen Elements ( O) der Menge aller Teilmengen ( y) des Alphabets (G ) erreicht.

Technische Details & Begründung:

Die Wahrscheinlichkeit 2 ^ -26 ergibt sich aus zwei Tatsachen: yWenn Sequenzen aufgerufen werden, ist dies die Potenzmengenfunktion, und es wird eine Liste aller Teilmengen der Eingabe erstellt. Da die Eingabe G26 Zeichen lang ist, hat diese Potenzmenge yG2 ^ 26 Einträge. OyGwählt ein zufälliges Element aus diesen 2 ^ 26 Einträgen aus. Genau einer dieser Einträge, die leere Zeichenfolge, wird bei der Übergabe an als falsch bewertetW die while-Schleife . Daher besteht jedes Mal eine Wahrscheinlichkeit von 2 ^ -26, die Schleife zu verlassen.

In jeder festen Anzahl von Schleifenzyklen K ist die Wahrscheinlichkeit, die Zahl K * 3,5 + m und K * 3,5 - m zu erhalten, gleich, weil jede Folge von Addenden, die eine Gesamtsumme erreicht, invertiert werden kann, -1 -> 8, 0 -> 7 usw., um den anderen zu erreichen. Zahlen, die näher an K * 3.5 liegen, sind deutlich wahrscheinlicher als weiter entfernte Zahlen. Wenn also K> 2000000 / 3.5 = 571428.5 ist, ist die Wahrscheinlichkeit, eine Zahl über 1000000 zu erhalten, größer als 75%, da einige der Ergebnisse über dieser Zahl in eine Eins-zu-Eins-Entsprechung mit allen Ergebnissen darunter gesetzt werden können Zahl und die obere Hälfte können in eine Eins-zu-Eins-Entsprechung mit denen unter 1000000 gestellt werden. Die Wahrscheinlichkeit, mindestens 571429 Schleifen zu erhalten, beträgt (1-2 ^ -26) ^ 571429, was nein ist weniger als (1-2 ^ -26 * 571429), Die erwartete Häufigkeit, mit der die Schleife während der ersten 571429 Versuche verlassen wird, ist 99,1%. Somit besteht bei 99,1% oder mehr der Versuche eine 75% ige oder größere Chance, mindestens 1000000 zu erhalten, und somit eine mehr als 50% ige Chance, über 1000000 zu gelangen.

Dieser Code basiert auf einem Verhalten, bei Odem ein Fehler vor 3 Tagen versehentlich aufgetreten ist und das heute behoben wurde. Es sollte auf jeder Version von Pyth 3 vor dem 22. Dezember oder nach dem heutigen Tag funktionieren. Der folgende Code ist äquivalent und hat immer funktioniert:

WOyG~ZtOUT)Z
isaacg
quelle
Was ist mit dem Online-Compiler passiert?
Optimierer
@Optimizer Probleme mit der Website, ich werde daran arbeiten.
Isaacg
Achso cool. Wollte gestern an der Pyth-Übersetzung meiner CJam-Antwort arbeiten und fand heraus, dass es 404 gibt.
Optimizer
0

Java, 113 Bytes

void g(){String a=Math.random()>0?"10":"01";for(;Math.random()>0;)a+=(int)(Math.random()*2);System.out.print(a);}

Dieses Programm druckt eine Binärzahl in den Standardausgabestream. Möglicherweise müssen Sie eine Weile warten, da die Wahrscheinlichkeit, dass die Zahl endet (oder positiv ist), ungefähr 0 beträgt. Die Vorstellung, dass der absolute Wert einer generierten Zahl weniger als 1 Million beträgt, ist amüsant, aber möglich.

Ungolfed:

void g(){
    String a=Math.random()>0?"10":"01";             //Make sure there are no trailing zeroes.
    for(;Math.random()>0;)a+=(int)(Math.random()*2);//Add digits
    System.out.print(a);                            //Print
}

Beispielausgabe: Wird veröffentlicht, wenn eine Nummer generiert wurde.

Die Nummer eins
quelle
0

Java (JDK) , 140 127 Byte

()->{int i;var o=System.out;for(o.print(i=(int)(19*Math.random())-10);i!=0&Math.random()<.9;)o.print((int)(11*Math.random()));}

-13 bytes indem Sie mehr Logik in den Loop-Header einbinden - dank @ceilingcat

Probieren Sie es online!

Sara J
quelle