Monte-Carlo-Schätzer von Pi


25

Happy Pi Day allerseits! Ohne jeden Grund versuche ich, einen Monte-Carlo-Schätzer für Pi zu konstruieren, der so kurz wie möglich ist. Können wir eine erstellen, die in einen Tweet passt?

Um das zu verdeutlichen, denke ich an den typischen Ansatz, zufällige Punkte aus dem Einheitsquadrat zu ziehen und das Verhältnis zu berechnen, das in den Einheitskreis fällt. Die Anzahl der Samples kann fest codiert sein oder nicht. Wenn Sie sie fest codieren, müssen Sie mindestens 1000 Beispiele verwenden. Das Ergebnis kann als Gleitkomma-, Festkomma- oder rationale Zahl zurückgegeben oder gedruckt werden.

Keine Triggerfunktionen oder Pi-Konstanten müssen ein Monte-Carlo-Ansatz sein.

Dies ist Codegolf, daher gewinnt die kürzeste Übermittlung (in Bytes).


2
sind Triggerfunktionen erlaubt? Ich schlage vor, Sie verbieten sie ausdrücklich.
Level River St

((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
John Dvorak

@JanDvorak Wie soll das gehen? Gibt mapIhnen das nicht eine Reihe von trueund false?
Martin Ender

@ MartinBüttner Ah, hoppla, sorry. .filter{...}.sizesollte aber funktionieren.
John Dvorak

@ JanDvorak In der Tat. Das ist wirklich ordentlich :)
Martin Ender

Antworten:


17

80386 Maschinencode, 40 38 Bytes

Hexdump des Codes:

60 33 db 51 0f c7 f0 f7 e0 52 0f c7 f0 f7 e0 58
03 d0 72 03 83 c3 04 e2 eb 53 db 04 24 58 db 04
24 58 de f9 61 c3

So erhalten Sie diesen Code (aus der Assemblersprache):

    // ecx = n (number of iterations)
    pushad;
    xor ebx, ebx; // counter
    push ecx; // save n for later
myloop:
    rdrand eax; // make a random number x (range 0...2^32)
    mul eax; // calculate x^2 / 2^32
    push edx;
    rdrand eax; // make another random number y
    mul eax; // calculate y^2 / 2^32
    pop eax;
    add edx, eax; // calculate D = x^2+y^2 / 2^32 (range 0...2^33)
    jc skip; // skip the following if outside the circle
    add ebx, 4; // accumulate the result multiplied by 4
skip:
    loop myloop;
    push ebx; // convert the result
    fild dword ptr [esp]; // to floating-point
    pop eax;
    fild dword ptr [esp]; // convert n to floating-point
    pop eax;
    fdivp st(1), st; // divide

    popad;
    ret;

Dies ist eine Funktion, die die MS- fastcallAufrufkonvention verwendet (Anzahl der Iterationen wird im Register übergeben ecx). Es gibt das Ergebnis im stRegister zurück.

Unterhaltsame Dinge über diesen Code:

  • rdrand - Nur 3 Bytes, um eine Zufallszahl zu generieren!
  • Es verwendet (vorzeichenlose) Ganzzahlarithmetik bis zur letzten Division.
  • Der Vergleich der quadratischen Distanz ( D) mit dem quadratischen Radius ( 2^32) wird automatisch durchgeführt - das Übertragsflag enthält das Ergebnis.
  • Um die Anzahl mit 4 zu multiplizieren, werden die Abtastwerte in Schritten von 4 gezählt.

Kommentar sollte lauten "Berechne x ^ 2% 2 ^ 32"
Cole Johnson

@ColeJohnson Nein - die Zufallszahl ist in eax; der mulBefehl multipliziert es mit sich selbst und setzt den hohen Anteil ein edx; Der untere Teil von eaxwird verworfen.
Anatolyg

11

Matlab / Octave, 27 Bytes

Ich weiß, dass es bereits eine Matlab / Octave-Antwort gibt, aber ich habe meinen eigenen Ansatz ausprobiert. Ich habe die Tatsache benutzt, dass das Integral 4/(1+x^2)zwischen 0 und 1 pi ist.

mean(4./(1+rand(1,1e5).^2))

Ein anderer Algorithmus ist immer toll! Auch effizienter!
Anatolyg

7

R, 40 (oder 28 oder 24 mit anderen Methoden)

mean(4*replicate(1e5,sum(runif(2)^2)<1))

mean(4*sqrt(1-runif(1e7)^2))

mean(4/(1+runif(1e7)^2))

Python 2, 56

Eine andere Python-Version, wenn dies erlaubt ist, aber ähnlich wie Matlab / Octave:

import numpy;sum(sum(numpy.random.rand(2,8e5)**2)<1)/2e5

6

Mathematica, 42 40 39 Bytes (oder 31/29?)

Ich habe drei Lösungen alle bei 42 Bytes:

4Count[1~RandomReal~{#,2},p_/;Norm@p<1]/#&
4Tr@Ceiling[1-Norm/@1~RandomReal~{#,2}]/#&
4Tr@Round[1.5-Norm/@1~RandomReal~{#,2}]/#&

Dies sind alle unbenannten Funktionen, die die Anzahl der Abtastwerte nmessen und eine rationale Approximation von π zurückgeben. Zunächst erzeugen sie alle nPunkte im Einheitsquadrat im positiven Quadranten. Dann bestimmen sie die Anzahl der Abtastwerte, die innerhalb des Einheitskreises liegen, und dividieren dann durch die Anzahl der Abtastwerte und multiplizieren mit 4. Der einzige Unterschied besteht darin, wie sie die Anzahl der Proben innerhalb des Einheitskreises bestimmen:

  • Der erste verwendet Countmit der Bedingung, dass Norm[p] < 1.
  • Der zweite subtrahiert die Norm jedes Punktes 1und rundet dann auf. Dies dreht Zahlen innerhalb des Einheitenkreises nach 1und solche außerhalb nach 0. Danach fasse ich sie alle zusammen Tr.
  • Die dritte Methode macht im Wesentlichen dasselbe, subtrahiert jedoch die von 1.5, sodass ich sie Roundanstelle von verwenden kann Ceiling.

Aaaaaund als ich das aufschrieb , kam mir der Gedanke , dass es tatsächlich eine kürzere Lösung gibt, wenn ich einfach subtrahiere 2und dann benutze Floor:

4Tr@Floor[2-Norm/@1~RandomReal~{#,2}]/#&

Oder speichern Sie ein anderes Byte mit den Unicode-Operatoren für Fußböden oder Decken:

4Tr@⌊2-Norm/@1~RandomReal~{#,2}⌋/#&
4Tr@⌈1-Norm/@1~RandomReal~{#,2}⌉/#&

Beachten Sie, dass die drei Runden-basierten Lösungen können auch mit geschrieben werden Meanstatt Trund ohne der /#wieder für das gleiche Bytes.


Wenn andere Monte-Carlo-basierte Ansätze in Ordnung sind (insbesondere der von Peter gewählte), kann ich 31 Bytes ausführen, indem ich das Integral von oder 29 unter Verwendung des Integrals von schätze . Diese Zeit wird als Gleitkommazahl angegeben:√(1-x2)1/(1+x2)

4Mean@Sqrt[1-1~RandomReal~#^2]&
Mean[4/(1+1~RandomReal~#^2)]&

9
Sie haben drei Lösungen für das Leben, das Universum und alles und Sie beschließen, es zu ruinieren? Ketzerei.
Siehe auch


6

CJam, 27 23 22 oder 20 Bytes

4rd__{{1dmr}2*mhi-}*//

2 Bytes gespart dank Runner112, 1 Byte gespart dank Sp3000

Es wird die Iterationszahl von STDIN als Eingabe verwendet.

Das ist so einfach wie es nur geht. Dies sind die wichtigsten Schritte:

  • Lesen Sie die Eingabe und führen Sie die Monte-Carlo-Iterationen so oft aus
  • Ermitteln Sie in jeder Iteration die Summe der Quadrate zweier zufälliger Gleitkommazahlen von 0 bis 1 und prüfen Sie, ob sie kleiner als 1 sind
  • Ermitteln Sie das Verhältnis von wie oft wir weniger als 1 durch Gesamtiterationen erhalten haben und multiplizieren Sie es mit 4, um PI zu erhalten

Code-Erweiterung :

4rd                     "Put 4 on stack, read input and convert it to a double";
   __{            }*    "Take two copies, one of them determines the iteration"
                        "count for this code block";
      {1dmr}2*          "Generate 2 random doubles from 0 to 1 and put them on stack";
              mh        "Take hypot (sqrt(x^2 + y^2)) where x & y are the above two numbers";
                i       "Convert the hypot to 0 if its less than 1, 1 otherwise";
                 -      "Subtract it from the total sum of input (the first copy of input)";
                    //  "This is essentially taking the ratio of iterations where hypot";
                        "is less than 1 by total iterations and then multiplying by 4";

Probieren Sie es hier online aus


Wenn der Durchschnittswert von 1/(1+x^2)auch als Monte Carlo betrachtet wird, kann dies in 20 Bytes erfolgen:

Urd:K{4Xdmr_*)/+}*K/

Probieren Sie es hier aus


2
Ich habe auch eine CJam-Antwort ausprobiert und es geschafft, in 2 Bytes unter Ihre Punktzahl zu kommen. Aber mein Code ist so ähnlich wie Ihr Code herausgekommen, dass ich mich dreckig fühle, wenn ich ihn als separate Antwort poste. Alles war gleich, bis auf die Variablenauswahl und diese beiden Optimierungen: Erhalte eine Zufallszahl von 0 bis 1 mit 1dmranstelle von KmrK/und überprüfe, ob die Summe der Quadrate größer als 1 mit ianstelle von ist 1>(ich fand das besonders clever) .
Runer112

@ Runer112 Danke. Der iTrick ist wirklich ordentlich! Und verdammt die fehlende Dokumentation für1dmr
Optimizer

5

Python 2, 77 75 Bytes

from random import*;r=random;a=0;exec"a+=r()**2+r()**2<1;"*4000;print a/1e3

Verwendet 4000 Samples, um Bytes zu speichern 1e3.


5
Sie könnten ein wenig mehr Genauigkeit ohne Kosten mit bekommen ...*8000;print a/2e3.
Logic Knight

5

Commodore 64 Basic, 45 Bytes

1F┌I=1TO1E3:C=C-(R/(1)↑2+R/(1)↑2<1):N─:?C/250

PETSCII-Substitutionen: = SHIFT+E, /= SHIFT+N, =SHIFT+O

Erzeugt 1000 Punkte im ersten Quadranten. Addiert für jedes die Wahrheit von "x ^ 2 + y ^ 2 <1" zu einer laufenden Zählung und dividiert dann die Zählung durch 250, um zu erhalten pi. (Das Vorhandensein eines Minuszeichens liegt daran, dass auf dem C64 "true" = -1 ist.)


Was macht (1)das?
Echristopherson

@echristopherson, du liest es falsch. /ist nicht das Teilungssymbol, sondern das Zeichen, das durch Eingeben SHIFT+Nauf einer Commodore 64-Tastatur erzeugt wird. R/(1)ist die Abkürzungsform für RND(1), dh. msgstr "eine Zufallszahl zwischen 0 und 1 mit dem aktuellen RNG - Startwert erzeugen".
Mark

Oh, du hast Recht! Gute alte PETSCII-Grafikcharaktere.
Echristopherson

5

J, 17 Bytes

Berechnet den Mittelwert der 40000Abtastwerte der Funktion 4*sqrt(1-sqr(x))im Bereich [0,1].

Handlich 0 o.xkehrt zurück sqrt(1-sqr(x)).

   1e4%~+/0 o.?4e4$0
3.14915

4

> <> (Fisch) , 114 Bytes

:00[2>d1[   01v
1-:?!vr:@>x|  >r
c]~$~< |+!/$2*^.3
 .41~/?:-1r
|]:*!r$:*+! \
r+)*: *:*8 8/v?:-1
;n*4, $-{:~ /\r10.

Jetzt hat> <> keinen eingebauten Zufallsgenerator. Es hat jedoch eine Funktion, die den Zeiger in eine zufällige Richtung sendet. Der Zufallsgenerator in meinem Code:

______d1[   01v
1-:?!vr:@>x|  >r
_]~$~< |+!/$2*^__
 __________
___________ _
_____ ____ _______
_____ ____~ ______

Grundsätzlich werden Zufallsbits generiert, aus denen eine Binärzahl besteht, und diese Zufallsbinärzahl wird dann in eine Dezimalzahl konvertiert.

Der Rest ist nur die regelmäßigen Punkte in der quadratischen Annäherung.

Verwendung: Wenn Sie den Code ausführen, müssen Sie sicherstellen, dass der Stack (-v im Python-Interpreter) beispielsweise mit der Anzahl der Samples gefüllt ist

pi.fish -v 1000

kehrt zurück

3.164

4

Matlab oder Octave 29 Bytes (danke an flawr!)

mean(sum(rand(2,4e6).^2)<1)*4

(Ich bin mir nicht ganz sicher, ob <1 in Ordnung ist. Ich habe gelesen, dass es <= 1 sein sollte. Aber wie groß ist die Wahrscheinlichkeit, genau 1 zu ziehen ...)

Matlab oder Octave 31 Bytes

sum(sum(rand(2,4e3).^2)<=1)/1e3

1
Sehr schöne Idee! Sie könnten mit zwei zusätzliche Bytes sparen mean(sum(rand(2,4e6).^2)<1)*4.
Fehler

4

Java, 108 Bytes

double π(){double π=0,x,i=0;for(;i++<4e5;)π+=(x=Math.random())*x+(x=Math.random())*x<1?1e-5:0;return π;}

Viertausend Iterationen, die jeweils 0,001 addieren, wenn sich der Punkt innerhalb des Einheitskreises befindet. Ziemlich einfaches Zeug.

Hinweis: Ja, ich weiß, dass ich durch Ändern πeines Einzelbytezeichens vier Bytes verlieren kann. Ich mag es so.


warum nicht 9999 Iterationen?
Optimierer

1
@Optimizer Es macht die Summe kürzer. Für 9999-Iterationen müsste ich stattdessen jedes Mal eine genauere Zahl hinzufügen, was mich Ziffern kostet.
Geobits

1
Sie können ein weiteres Byte speichern und die Genauigkeit verbessern, indem Sie "4e5" und "1e-5" für die Zahlen verwenden.
Vilmantas Baranauskas

@ VilmantasBaranauskas Danke! Das vergesse ich immer :) Es ist verlockend, stattdessen 4e9 und 1e-9 zu verwenden, aber das dauert eine ganze Weile ...
Geobits

Protip: Beim Golfen sollte man eigentlich die Bytes reduzieren, nicht künstlich erhöhen
Destructible Lemon

3

Javascript: 62 Bytes

for(r=Math.random,t=c=8e4;t--;c-=r()**2+r()**2|0);alert(c/2e4)

Ich habe die vorherige (jetzt gelöschte) Javascript-Antwort verwendet und 5 Bytes rasiert.



Ihre Antwort scheint ein Snippet zu sein, dessen Eingabe / Ausgabe nicht zulässig ist . Bitte korrigiere oder lösche deinen Beitrag.
Jonathan Frech

Tut mir leid, ich bin neu, ich wusste nicht, wie ich den Link zur vorherigen Lösung setzen soll, die jetzt angezeigt wird, wurde gelöscht. Hinsichtlich des Snippets: Ich stimme vollkommen zu, aber das war der Code der vorherigen Javascript-Lösung, die ich auch aus diesem Grund für ungültig halte. Ich habe mein Programm so modifiziert, dass es ein Programm ist.
Guzman Tierno

Ja; Die vorherige Antwort wurde gelöscht, da sie ungültig war. Ich habe Ihre Antwort gesehen, bevor ich das Löschen empfohlen habe, daher der Kommentar. +1 für das Einreichen einer gültigen Antwort; Willkommen bei PPCG!
Jonathan Frech

2

GolfScript (34 Zeichen)

0{^3?^rand.*^.*+/+}2000:^*`1/('.'@

Online-Demo

Hier wird ein fester Punkt verwendet, da GS eigentlich keinen Fließkommawert hat. Die Verwendung von Fixpunkten wird leicht missbraucht. Wenn Sie also die Iterationszahl ändern möchten, stellen Sie sicher, dass es sich um eine doppelte Zehnerpotenz handelt.

Gutschrift an xnor für die jeweils angewandte Monte-Carlo-Methode.


2

Python 2, 90 85 81 Bytes

from random import*;r=random;print sum(4.for i in[0]*9**7if r()**2+r()**2<1)/9**7

kehrt 3.14120037157zum Beispiel zurück. Die Stichprobenanzahl beträgt 4782969 (9 ^ 7). Sie können mit 9 ^ 9 ein besseres pi erzielen, aber Sie müssen geduldig sein.


Sie können maximal 3 durch Ersetzen sparen range(9**7)mit [0]*9**7oder etwas, da Sie nicht verwenden i. Und die Liste ist nicht zu lang, um auf Speicherprobleme zu stoßen.
Sp3000

Vielen Dank. Ich wollte loswerden, range()aber ich hatte diesen Trick völlig vergessen.
Logic Knight

Ich habe das Gefühl [0]9**7, dass die Syntax nicht gültig ist.
Siehe auch

Du hast recht. Ich habe das verlorene Sternchen wieder angebracht (es war unter meinem Schreibtisch).
Logic Knight

2

Ruby, 39 Bytes

p (1..8e5).count{rand**2+rand**2<1}/2e5

Einer der Höhepunkte ist, dass dieser die 8e5Notation verwenden kann, wodurch er auf ~ 8e9 Samples in derselben Programmbytezahl erweiterbar ist.



1

Scala, 87 77 66 Bytes

def s=math.pow(math.random,2);Seq.fill(1000)(s+s).count(_<1)/250d

Wenn Sie 1000mit 8000und 250dmit ersetzen, 2e4sparen Sie ein Byte und erhöhen die Anzahl der Samples um den Faktor 8.
Dave Swartz

1

Pure Bash, 65 Bytes

for((;i++<$1*4;a+=RANDOM**2+RANDOM**2<32767**2));{ :;}
echo $a/$1

Nimmt einen einzelnen Befehlszeilenparameter an, der mit 4 multipliziert wird, um die Anzahl der Stichproben zu erhalten. Bash-Arithmetik ist nur eine Ganzzahl, daher wird eine Rationale ausgegeben. Dies kann bc -lfür die Enddivision weitergeleitet werden:

$ ./montepi.sh 10000
31477/10000
$ ./montepi.sh 10000|bc -l
3.13410000000000000000
$ 

1

Joe , 20 bis 19 Bytes

Hinweis: Diese Antwort ist nicht konkurrierend, da Version 0.1.2, die die Zufälligkeit erhöht hat, nach dieser Herausforderung veröffentlicht wurde.

Benannte Funktion F:

:%$,(4*/+1>/+*,?2~;

Unbenannte Funktion:

%$,(4*/+1>/+*,?2~;)

Beide verwenden die Anzahl der Stichproben als Argument und geben das Ergebnis zurück. Wie arbeiten Sie?

%$,(4*/+1>/+*,?2~;)
   (4*/+1>/+*,?2~;) defines a chain, where functions are called right-to-left
               2~;  appends 2 to the argument, giving [x, 2]
              ?     create a table of random values from 0 to 1 with that shape
            *,      take square of every value
          /+         sum rows, giving a list of (x**2+y**2) values
        1>           check if a value is less than 1, per atom
      /+             sum the results
    4*               multiply by four
%$,                  divide the result by the original parameter

Beispiel läuft:

   :%$,(4*/+1>/+*,?2~;
   F400000
3.14154
   F400000
3.14302

1

dc, 59 zeichen (whitespace wird ignoriert)

[? 2^ ? 2^ + 1>i]su
[lx 1+ sx]si
[lu x lm 1+ d sm ln>z]sz

5k
?sn
lzx
lx ln / 4* p
q

Ich habe dies auf Plan 9 und OpenBSD getestet, also stelle ich mir vor, dass es unter Linux (GNU?) Funktionieren wird dc.

Erklärung nach Zeile:

  1. Speichert Code in [read und square two floats; Führen Sie das Register aus, iwenn 1 größer ist als die Summe der Quadrate] im Register u.
  2. Speichert den Code xim Register [Inkrementiere das Register um 1]i .
  3. Speichert Code im Register [Register ausführen, Register uinkrementieren mund dann Register ausführen, zwenn Register mgrößer als Register ist n] z.
  4. Stellen Sie die Skala auf 5 Dezimalstellen ein.

  5. Lesen Sie die Anzahl der abzutastenden Punkte aus der ersten Eingabezeile.
  6. Register ausführen z.
  7. Teilen Sie das Register x(die Anzahl der Treffer) durch das Registern (die Anzahl der Punkte), multiplizieren Sie das Ergebnis mit 4 und drucken Sie es aus.
  8. Verlassen.

Ich habe jedoch betrogen:

Das Programm benötigt eine Zufallsmenge zwischen 0 und 1.

/* frand.c */
#include <u.h>
#include <libc.h>

void
main(void)
{
    srand(time(0));

    for(;;)
        print("%f\n", frand());
}

Verwendung:

#!/bin/rc
# runpi <number of samples>

{ echo $1; frand } | dc pi.dc

Testlauf:

% runpi 10000
3.14840

Jetzt mit weniger Betrug (100 Bytes)

Jemand wies darauf hin, dass ich ein einfaches Prng einschließen könnte.
http://en.wikipedia.org/wiki/RANDU

[lrx2^lrx2^+1>i]su[lx1+sx]si[luxlm1+dsmln>z]sz[0kls65539*2 31^%dsslkk2 31^/]sr?sn5dksk1sslzxlxlm/4*p

Ungolfed

[
Registers:
u - routine : execute i if sum of squares less than 1
i - routine : increment register x
z - routine : iterator - execute u while n > m++
r - routine : RANDU PRNG
m - variable: number of samples
x - variable: number of samples inside circle
s - variable: seed for r
k - variable: scale for division
n - variable: number of iterations (user input)
]c
[lrx 2^ lrx 2^ + 1>i]su
[lx 1+ sx]si
[lu x lm 1+ d sm ln>z]sz
[0k ls 65539 * 2 31^ % d ss lkk 2 31 ^ /]sr
? sn
5dksk
1 ss
lzx
lx lm / 4*
p

Testlauf:

$ echo 10000 | dc pigolf.dc
3.13640

1

Pyth, 19

c*4sm<sm^OQ2 2*QQQQ

Geben Sie die gewünschte Anzahl von Iterationen als Eingabe ein.

Demonstration

Da Pyth keine "Random Floating Number" -Funktion hat, musste ich improvisieren. Das Programm wählt zwei zufällige positive ganze Zahlen aus, die kleiner sind als die Eingabe, Quadrate, Summen und die mit der Eingabe im Quadrat verglichen werden. Dies wurde so oft durchgeführt, wie es der Eingabe entsprach, dann wird das Ergebnis mit 4 multipliziert und durch die Eingabe dividiert.

In ähnlichen Nachrichten werde ich in Kürze eine zufällige Gleitkommaoperation zu Pyth hinzufügen. Dieses Programm verwendet diese Funktion jedoch nicht.


Wenn wir interpretieren "Das Ergebnis kann als Gleitkomma, Festkomma oder rationale Zahl zurückgegeben oder gedruckt werden." großzügig, dann sollte das Drucken des Zählers und des Nenners der resultierenden Fraktion ausreichen. In diesem Fall:

Pyth, 18

*4sm<sm^OQ2 2*QQQQ

Dies ist ein identisches Programm, bei dem die Gleitkommadivisionsoperation ( c) entfernt wurde.


1

Julia, 37 Bytes

4mean(1-floor(sum(rand(4^8,2).^2,2)))

Die Anzahl der Stichproben beträgt 65536 (= 4 ^ 8).

Eine etwas längere Variante: Eine Funktion mit der Anzahl der Samples sals einziges Argument:

s->4mean(1-floor(sum(rand(s,2).^2,2)))

1

C 130 Bytes

#include<stdlib.h>f(){double x,y,c=0;for(int i=0;i<8e6;++i)x=rand(),y=rand(),c+=x*x+y*y<1.0*RAND_MAX*RAND_MAX;printf("%f",c/2e6);}

Ungolfed:

#include <stdlib.h>
f(){
 double x,y,c=0;
 for(int i=0; i<8e6; ++i) x=rand(), y=rand(), c+=x*x+y*y<1.0*RAND_MAX*RAND_MAX;
 printf("%f",c/2e6);
}

Natürlich solltest du die Version wahrscheinlich immer noch ohne Leerzeichen posten (behalte die aktuelle Version mit der Überschrift "ungolfed / with whitespace" oder so)
Destructible Lemon

@DestructibleWatermelon fertig!
Karl Napf

Die Lösung funktioniert in GCC nicht ohne vorherige Zeilenumbruch f(). Welchen Compiler hast du benutzt? Siehe tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/…
eush77


1

Eigentlich 14 Bytes (nicht konkurrierend)

`G²G²+1>`nkæ4*

Probieren Sie es online!

Diese Lösung ist nicht konkurrierend, da die Sprache die Herausforderung postdatiert. Die Anzahl der Samples wird als Eingabe angegeben (nicht fest codiert).

Erläuterung:

`G²G²+1>`nkæ4*
`G²G²+1>`n      do the following N times:
 G²G²+            rand()**2 + rand()**2
      1>          is 1 greater?
          kæ    mean of results
            4*  multiply by 4

2
Warum die Gegenstimme?
Destructible Lemon

1

Schläger 63 Bytes

Mit der Methode der R-Sprache Antwort von @Matt:

(/(for/sum((i n))(define a(/(random 11)10))(/ 4(+ 1(* a a))))n)

Ungolfed:

(define(f n)
   (/
    (for/sum ((i n))
      (define a (/(random 11)10))
      (/ 4(+ 1(* a a))))
    n))

Testen:

(f 10000)

Leistung (Bruchteil):

3 31491308966059784/243801776017028125

Als Dezimalzahl:

(exact->inexact(f 10000))

3.13583200307849

1

Fortran (gfortran) , 84 83 Bytes

CALL SRAND(0)
DO I=1,4E3
X=RAND()
Y=RAND()
IF(X*X+Y*Y<1)A=A+1E-3
ENDDO
PRINT*,A
END

Probieren Sie es online!

Dieser Code ist sehr schlecht geschrieben. Es schlägt fehl, wenn gfortran entscheidet, eine Variable Amit einem anderen Wert als 0 zu initialisieren (was ungefähr 50% der Kompilierungen entspricht), und wenn Aes mit 0 initialisiert wird, wird immer dieselbe zufällige Sequenz für den angegebenen Startwert generiert. Dann wird immer der gleiche Wert für Pi ausgegeben.

Dies ist ein viel besseres Programm:

Fortran (GFortran) , 100 bis 99 Bytes

A=0
DO I=1,4E3
CALL RANDOM_NUMBER(X)
CALL RANDOM_NUMBER(Y)
IF(X*X+Y*Y<1)A=A+1E-3
ENDDO
PRINT*,A
END

Probieren Sie es online!

(Ein Byte in jeder Version gespeichert; danke Penguino).


1
In jeder Version können Sie ein Byte speichern, indem Sie 'DO I = 1,1E3' in 'DO I = 1,4E3' ändern, 'A = A + 1' in 'A = A + 1E-3' ändern und ' DRUCKEN *, A / 250 'bis' DRUCKEN *, A '
Penguino

Ja, da bist du dir sicher! Danke für den Vorschlag!
Rafa11111

1

Japt , 26 oder 18 Bytes

o r_+ÂMhMr p +Mr p <1Ã*4/U

Probieren Sie es online!

Analog zu Optimizers Antwort , hauptsächlich um Japt zu lernen.
Legt die Anzahl der auszuführenden Iterationen als implizite Eingabe fest U.

o                           Take the input and turn it into a range [0, U),
                            essentially a cheap way to get a large array.
  r_                        Reduce it with the default initial value of 0.
    +Â                      On each iteration, add one if
      MhMr p +Mr p          the hypotenuse of a random [0,1)x[0,1) right triangle
                   <1       is smaller than one.
                     Ã*4/U  Multiply the whole result by four and divide by input.

Wenn dies 1/(1+x^2)erlaubt ist (anstelle von zwei getrennten Zufällen), können wir mit derselben Logik 18 Bytes erreichen.

o r_Ä/(1+Mr pÃ*4/U

1
Sie können ein paar Bytes einsparen, indem Sie Mhdie Hypotenuse berechnen lassen , anstatt sie selbst zu machen ;-) Sie können xauch die Summe eines Arrays verwenden, anstatt sie durch Addition zu reduzieren:o x@MhMr Mr)<1Ã*4/U
ETHproductions

@ETHproductions Schön, ich wusste nicht, dass du so etwas verwenden kannst Mh, danke! Deine zwei zufällige Antwort ist fast so kurz wie meine Antwort mit nur einer zufälligen, das ist ziemlich cool. Ich werde xbedenken, ich neige dazu, beim Golfspiel viel Reduktion zu verwenden, daher ist dies sehr praktisch.
Nit

1

F #, 149 Bytes

open System;
let r=new Random()
let q()=
 let b=r.NextDouble()
 b*b
let m(s:float)=(s-Seq.sumBy(fun x->q()+q()|>Math.Sqrt|>Math.Floor)[1.0..s])*4.0/s

Probieren Sie es online!

Soweit ich das beurteilen kann, ist es für diese Art der Summierung in F # kürzer, ein Array von Zahlen zu erstellen und die Seq.sumByMethode zu verwenden, als einen for..to..doBlock zu verwenden.

Mit diesem Code wird eine Auflistung von Gleitkommazahlen von 1 bis erstellt s, die Funktion fun x->...für die Anzahl der Elemente in der Auflistung ausgeführt und das Ergebnis summiert. Es gibt sElemente in der Sammlung, so dass der Zufallstest smal durchgeführt wird. Die tatsächlichen Zahlen in der Sammlung werden ignoriert ( fun x->aber xnicht verwendet).

Dies bedeutet auch, dass die Anwendung zuerst das Array erstellen und füllen und dann darüber iterieren muss. Es ist also wahrscheinlich doppelt so langsam wie eine for..to..doSchleife. Und bei der Array-Erstellung liegt die Speichernutzung im Bereich von O (f ** k)!

Für den eigentlichen Test selbst if then elseberechnet er anstelle einer Anweisung den Abstand ( q()+q()|>Math.Sqrt) und rundet ihn abMath.Floor . Wenn der Abstand innerhalb des Kreises liegt, wird er auf 0 abgerundet. Wenn der Abstand außerhalb des Kreises liegt, wird er auf 1 abgerundetSeq.sumBy Methode addiert dann diese Ergebnisse.

Beachten Sie dann, dass Seq.sumBydie Summe nicht die Punkte ist innerhalb des Kreises , sondern die Punkte außerhalb des Kreises . Also für das Ergebnis braucht ess (unsere Stichprobengröße) und subtrahiert die Summe davon.

Es scheint auch, dass das Verwenden einer Stichprobengröße als Parameter kürzer ist als das Festcodieren des Werts. Also betrüge ich ein bisschen ...


1

Haskell, 116 114 110 96 Bytes

d=8^9
g[a,b]=sum[4|a*a+b*b<d*d]
p n=(sum.take(floor n)$g<$>iterate((\x->mod(9*x+1)d)<$>)[0,6])/n

Da der Umgang mit import System.Random; r=randoms(mkStdGen 2)zu vielen wertvollen Bytes zu viel Zeit in Anspruch nimmt, erstelle ich mit dem linearen Kongruenzgenerator eine unendliche Liste von Zufallszahlen, von denen manche sagen, dass sie fast kryptografisch stark sind:x↦x*9+1 mod 8^9 , die von der Hull-Dobell Satz den gesamten Zeitraum hat 8^9.

g Ausbeuten 4 wenn der Zufallszahlenpunkt innerhalb des Kreises für Zufallszahlenpaare liegt, [0..8^9-1]da dies eine Multiplikation in der verwendeten Formel eliminiert.

Verwendung:

> p 100000
3.14208

Probieren Sie es online!


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.