Casuale golf del giorno # 2: numeri da una distribuzione normale


12

Informazioni sulla serie

Prima di tutto, puoi trattarlo come qualsiasi altra sfida di golf del codice e rispondere senza preoccuparti della serie. Tuttavia, esiste una classifica in tutte le sfide. Puoi trovare la classifica insieme ad alcune ulteriori informazioni sulla serie nel primo post .

Anche se ho un sacco di idee in programma per la serie, le sfide future non sono ancora state messe sulla pietra. Se hai suggerimenti, per favore fatemelo sapere sul post sandbox pertinente .

Buca 2: numeri da una distribuzione normale

Non riesco a credere che non sia stato ancora fatto! Devi generare numeri casuali, attingendo da una distribuzione normale . Alcune regole (la maggior parte di esse è probabilmente automaticamente coperta dalla maggior parte delle presentazioni, ma alcune sono in atto per garantire la coerenza dei risultati tra lingue molto diverse):

  • Dovresti prendere due numeri interi non negativi come input : un seme Se la quantità Ndi numeri da restituire. L'output dovrebbe essere un elenco di Nnumeri in virgola mobile, tratti da una distribuzione normale con media 0 e varianza 1 . Ogni volta che alla tua presentazione viene dato lo stesso seme S, dovrebbe produrre lo stesso numero. In particolare, se viene chiamato una volta con e una volta con , le prime voci delle due uscite dovrebbero essere identiche. Inoltre, almeno 2 16 valori diversi di dovrebbero produrre sequenze diverse.(S, N1)(S, N2)min(N1, N2)S

  • Puoi usare qualsiasi generatore di numeri casuali incorporato che sia documentato per disegnare numeri da una distribuzione (approssimativamente) uniforme , a condizione che tu possa passarci Ssopra e che supporti almeno 2 16 semi diversi. In tal caso, l'RNG dovrebbe essere in grado di restituire almeno 2 20 valori diversi per ogni dato numero richiesto da esso.

  • Se il tuo RNG uniforme disponibile ha un intervallo più piccolo, non è seminabile o supporta un numero troppo basso di semi, devi prima costruire un RNG uniforme con un intervallo sufficientemente ampio sopra quello incorporato oppure devi implementare il tuo RNG adatto usando il seme. Questa pagina può essere utile per questo.
  • Se non si implementa un algoritmo stabilito per la generazione di distribuzioni normali, si prega di includere una prova di correttezza. In entrambi i casi, l'algoritmo scelto deve produrre una distribuzione normale teoricamente esatta (salvo limitazioni del PRNG sottostante o tipi di dati a precisione limitata).
  • L'implementazione dovrebbe utilizzare e restituire numeri in virgola mobile (almeno 32 bit di larghezza) o numeri in virgola fissa (almeno 24 bit di larghezza) e tutte le operazioni aritmetiche dovrebbero utilizzare l'intera larghezza del tipo scelto.
  • Non è necessario utilizzare alcuna funzione integrata direttamente correlata alla distribuzione normale o agli integrali gaussiani, come la funzione Errore o il suo contrario.

È possibile scrivere un programma completo o una funzione e accettare input tramite STDIN, argomento della riga di comando, argomento della funzione o prompt e produrre output tramite il valore restituito o stampando su STDOUT (o l'alternativa più vicina).

Se Nsaranno numeri interi non negativi, ciascuno inferiore a 2 20 . L'output può essere in qualsiasi elenco o formato stringa comodo e inequivocabile.

Questo è il golf del codice, quindi vince l'invio più breve (in byte). E, naturalmente, anche l'invio più breve per utente entrerà nella classifica generale della serie.

Classifica

Il primo post della serie genera una classifica.

Per assicurarti che le tue risposte vengano visualizzate, inizia ogni risposta con un titolo, utilizzando il seguente modello Markdown:

# Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(La lingua non è attualmente visualizzata, ma lo snippet richiede e analizza, e in futuro potrei aggiungere una classifica per lingua.)


Aspetta, possiamo usare RNG con intervallo non intero?
mniip,

Le risposte esistenti su PS 2 sembrano utilizzare [0, 1) RNG in virgola mobile, è consentito?
mniip,

@mniip Sì, sono ammessi RNG a virgola mobile, purché siano uniformi, seminabili e in grado di restituire il numero richiesto di galleggianti distinti.
Martin Ender,

Risposte:


8

Dyalog APL, 33 byte

{(.5*⍨¯2×⍟?0)×1○○2×?0}¨⍳⎕⊣⎕rl←1+⎕

Box-Muller :

⎕         ⍝ evaluated input
⎕rl←1+⎕   ⍝ set APL's random seed to 1+⎕ (S)
          ⍝   add 1 because ⎕rl←0 has special meaning: sets the seed randomly
{ }¨⍳N    ⍝ do the thing in braces N times
?0        ⍝ random number 0≤x<1
1○○2×A    ⍝ sin(2πA)
.5*⍨¯2×⍟B ⍝ sqrt(-2lnB)

Sono abbastanza sicuro che questo non possa essere battuto da nessun'altra lingua.
Zero Fiber

2
Questo non soddisfa questa regola: "In particolare, se viene chiamato una volta con (S, N1) e una volta con (S, N2), le prime voci min (N1, N2) delle due uscite dovrebbero essere identiche".
Marin

@marinus Grazie, risolto. Ho anche cambiato ⎕rlin S+1perché ⎕rl←0ha un significato speciale.
ngn

Probabilmente in realtà non ti serve +1, tutto ciò che dice è che devi supportare almeno 2 ^ 16 valori diversi. Quindi, funzionando correttamente nell'intervallo [1..2 ^ 16] dovrebbe essere OK.
Marin

S = 0 renderebbe il calcolo non ripetibile, il che viola la regola sopra citata.
ngn,

8

R, 68 byte

function(S,N){set.seed(S);sqrt(-2*log(runif(N)))*cos(2*pi*runif(N))}

Questo utilizza la runif()funzione, che genera deviazioni casuali da una distribuzione uniforme. Il seme per la generazione di numeri casuali viene specificato utilizzando set.seed(), che per impostazione predefinita utilizza l'algoritmo Mersenne-Twister con un periodo di 2 ^ 19937-1.

Il risultato è un vettore R di lunghezza N contenente gli scostamenti normali standard calcolati.

Questo utilizza il metodo Box-Muller: per due variabili casuali uniformi indipendenti U e V, inserisci qui la descrizione dell'immagine


Se questa è sintassi valida in R, puoi tralasciare f=(la funzione non ha necessariamente bisogno di essere nominata, se le funzioni senza nome fanno parte della tua lingua).
Martin Ender,

@ MartinBüttner: apprezzo il suggerimento, ma per quanto ne so R non saprebbe cosa fare con una funzione senza nome.
Alex A.

Error: unexpected '}' in "f=fu...Inoltre ricevo sempre un messaggio di errore , sei sicuro di ricevere gli stessi primi numeri se chiami f(0,1)e f(0,2)?
Flawr

4

Dyalog APL, 42 34

{⎕RL←⍺⋄{(.5*⍨¯2×⍟⍺)×1○⍵×○2}/?⍵2⍴0}

Questa è una funzione che assume Scome argomento di sinistra e Ncome argomento di destra.

     5{⎕RL←⍺⋄{(.5*⍨¯2×⍟⍺)×1○⍵×○2}/?⍵2⍴0}10
3.019132549 ¯0.2903143175 ¯0.7353414637 1.421417015 2.327544764 ¯0.00005019747711 ¯0.9582127248 ¯0.2764568462
      ¯0.1602736853 ¯0.9912352616
     5{⎕RL←⍺⋄{(.5*⍨¯2×⍟⍺)×1○⍵×○2}/?⍵2⍴0}20
3.019132549 ¯0.2903143175 ¯0.7353414637 1.421417015 2.327544764 ¯0.00005019747711 ¯0.9582127248 ¯0.2764568462
      ¯0.1602736853 ¯0.9912352616 0.642585109 ¯0.2450019151 ¯0.415034463 0.03481768503 ¯0.4621212815 ¯0.760925979
      0.2592913013 1.884867889 ¯0.9621252731 0.3062560446

È un'implementazione della trasformazione di Box-Muller, che utilizza l'operatore casuale incorporato di Dyalog APL ?, che per impostazione predefinita è un tornado di Mersenne che restituisce valori a 64 bit, il che dovrebbe essere sufficiente.

Spiegazione:

  • ⎕RL←⍺: imposta il seme casuale su .
  • ?⍵2⍴0: genera coppie di numeri casuali tra 0 e 1.
  • {... }/: applica la seguente funzione a ciascuna coppia:
    • (.5*⍨¯2×⍟⍺)×1○⍵×○2: calcola il Z0valore ( sqrt(-2 ln ⍺)×cos(2π⍵)).

1
In v14.0 ?0restituisce un numero in virgola mobile compreso tra 0 e 1.
ngn

3

Perl, 67

sub f{srand$_[0];map{cos(atan2(1,1)*rand 8)*sqrt-2*log rand}1..pop}

Box-Muller come in altre voci. faccetta i parametri in ordine S, N.

Uso:

$ perl -le 'sub f{srand$_[0];map{cos(atan2(1,1)*rand 8)*sqrt-2*log rand}1..pop}print for f(5,3)'
-1.59212831801942
0.432167710756345
-0.533673305924252

3

Java, 164 161 byte

class B extends java.util.Random{B(int s,int n){super(s);for(;n-->0;System.out.println(Math.sqrt(-2*Math.log(nextDouble()))*Math.cos(2*Math.PI*nextDouble())));}}

Ciò accetta input tramite la funzione e output tramite stdout. Utilizza il metodo Box-Muller.


5
s=0;s++<n;-> ;n-->0;?
Geobits il

1
@Geobits Sembra una lambda: D
TheNumberOne

3

Commodore 64 Basic, 76 70 63 byte

1INPUTS,N:S=R/(-S):F┌I=1TON:?S●(-2*LOG(R/(1)))*S╮(2*π*R/(1)):N─

Poiché il set di caratteri PETSCII contiene alcuni simboli non presenti in Unicode, ho effettuato delle sostituzioni: /= SHIFT+N, = SHIFT+O, = SHIFT+Q, = SHIFT+I, =SHIFT+E

Questo implementa la trasformata Box-Muller standard per generare i numeri; Ho scelto sin (x) metà della trasformazione perché Commodore 64 Basic ha una scorciatoia di due caratteri per sin(), ma non per cos().

Anche se il manuale indica altrimenti, il valore dell'argomento RND non importa: se è passato un numero negativo, il generatore di numeri casuali non è semplicemente ri-seminato, viene ri-seminato con quel numero . Questo rende il seeding molto più semplice: invece di dover ricorrere a POKEcinque posizioni di memoria, devo semplicemente effettuare una chiamata nulla RND, che riduce il codice da due righe / 121 byte a 1 riga / 76 byte.

Modifica: golfato sei byte fuori realizzando che potevo combinare le due INPUTaffermazioni e che lo spazio dopo TOera facoltativo.

Modifica: ne ho vinte altre sette: Commodore Basic, infatti, ha Pi come costante incorporata, ed è persino digitabile su una tastiera moderna ( SHIFT+PgDnnel caso te lo stavi chiedendo).


3

80386 codice macchina, 72 byte

Hexdump del codice:

60 8b 7c 24 24 33 ed 8d 75 fb 8d 46 79 f7 e2 f7
f6 8b da b3 7f 0f cb d1 eb 89 1f d9 07 d9 e8 de
e9 33 ee 75 e5 d9 ed d9 c9 d9 f1 dc c0 d9 e0 d9
fa d9 c9 d9 eb de c9 dc c0 d9 ff de c9 d9 1f 83
c7 04 e2 c6 61 c2 04 00

Ecco il codice sorgente (può essere compilato da Visual Studio):

__declspec(naked) void __fastcall doit(int count, unsigned seed, float* output)
{
    _asm {
                                // ecx = count
                                // edx = seed
        // save registers
        pushad;
        mov edi, [esp + 0x24];  // edi = pointer to output
        xor ebp, ebp;           // ebp = 0
        lea esi, [ebp - 5];     // esi = 4294967291 (a prime number)

    myloop:
        // Calculate the next random number
        lea eax, [esi + 121];   // eax = 116
        mul edx;
        div esi;
        mov ebx, edx;

        // Convert it to a float in the range 1...2
        mov bl, 0x7f;
        bswap ebx;
        shr ebx, 1;

        // Convert to range 0...1 and push onto the FPU stack
        mov [edi], ebx;
        fld dword ptr [edi];
        fld1;
        fsubp st(1), st;

        // Make 2 such random numbers
        xor ebp, esi;
        jnz myloop;

        // Calculate sqrt(-2*ln(x))
        fldln2;
        fxch;
        fyl2x;
        fadd st, st(0);
        fchs;
        fsqrt;

        // Calculate cos(2*pi*y)
        fxch st(1);
        fldpi;
        fmul;
        fadd st, st(0);
        fcos;

        // Calculate and write output
        fmulp st(1), st;
        fstp dword ptr [edi];
        add edi, 4;

        // Repeat
        loop myloop

        // Return
        popad;
        ret 4;
    }
}

Qui uso un generatore di numeri casuali Lehmer . Utilizza il seguente algoritmo:

x(k+1) = 116 * x(k) mod 4294967291

Qui 4294967291 è un numero primo (2 ^ 32-5) grande, e 116 è un numero piccolo (meno di 128; vedi sotto) che è la sua radice primitiva . Ho scelto una radice primitiva che ha una distribuzione più o meno casuale di zeri e di quelli nella rappresentazione binaria (01110100). Questo RNG ha il periodo massimo possibile di 4294967290, se il seme è diverso da zero.


I numeri relativamente piccoli che ho usato qui (116 e 4294967291, che possono essere rappresentati anche come -5) mi permettono di trarre vantaggio dalla leacodifica dell'istruzione:

8d 46 79     lea eax, [esi+121]

È assemblato a 3 byte se i numeri possono rientrare in 1 byte.


La moltiplicazione e la divisione usano edxe eaxcome i loro registri di lavoro, motivo per cui ho creato seedil secondo parametro per la funzione ( fastcallchiamando convention usa edxper passare il secondo parametro). Inoltre, viene passato il primo parametro ecx, che è un buon posto per contenere un contatore: un loop può essere organizzato in 1 istruzione!

e2 c6        loop myloop

Per convertire un numero intero in un numero in virgola mobile, ho sfruttato la rappresentazione di numeri in virgola mobile a precisione singola: se imposto i 9 bit (esponente) alti sul modello di bit 001111111e lascio casuali i 23 bit bassi, ottenere un numero casuale nell'intervallo 1 ... 2. Ho preso l'idea da qui . Per impostare i 9 bit alti, ho usato alcuni bit-fiddling su ebx:

mov ebx, edx;    xxxxxxxx|yyyyyyyy|zzzzzzzz|aaaaaaaa
mov bl, 0x7f;    xxxxxxxx|yyyyyyyy|zzzzzzzz|01111111
bswap ebx;       01111111|zzzzzzzz|yyyyyyyy|xxxxxxxx
shr ebx, 1;      00111111|1zzzzzzz|zyyyyyyy|yxxxxxxx

Per generare due numeri casuali, ho usato un ciclo nidificato di 2 iterazioni. L'ho organizzato con xor:

xor ebp, esi;    first time, the result is -5
jnz myloop;      second time, the result is 0 - exit loop

Il codice in virgola mobile implementa la trasformazione Box-Muller .


2

Haskell, 118  144 

import System.Random;h z=let(u,r)=random z in(cos$2*pi*fst(random r)::Float)*sqrt(-2*log u):h r;g=(.(h.mkStdGen)).take

Esempio di utilizzo:

*Main> g 3 0x6AE4A92CAFA8A742
[0.50378895,-0.20593005,-0.16684927]
*Main> g 6 0x6AE4A92CAFA8A742
[0.50378895,-0.20593005,-0.16684927,1.1229043,-0.10026576,0.4279402]
*Main> g 6 0xE09B1088DF461F7D
[2.5723906,-0.5177805,-1.3535261,0.7400385,3.5619608e-3,-8.246434e-2]

Il tipo restituito di randomè vincolato a Float, il che fa randomgenerare un float uniforme in [0, 1). Da quel momento in poi è una formula box-muller semplice con qualche magia inutile per la generazione di liste.


2

Golflua, 63 70

Informazioni e istruzioni Golflua.

\g(n,s)`_ENV,b=M,{}rs(s)~@i=1,n b[i]=q(l(r()^-2))*c(r()*pi)$~b$

Restituisce una tabella contenente i valori. Nell'esempio che sto usando ~T.u( ), che è lo stesso return table.unpack( )di lua.

> ~T.u(g(3,1234567))
0.89302672974232 0.36330401643578 -0.64762161593981
> ~T.u(g(5,1234567))
0.89302672974232 0.36330401643578 -0.64762161593981 -0.70654636393063 -0.65662878785425
> ~T.u(g(5,7654321))
0.3867923683064 -0.31758512485963 -0.58059120409317 1.2079459300077 1.1500121921242

Molti caratteri sono stati salvati impostando l'ambiente della funzione su M(aka math).


2

SAS, 108

Ho già pubblicato una risposta in R che è più breve di questa, ma ci sono pochissime risposte SAS su PPCG, quindi perché non aggiungerne un'altra?

%macro f(s,n);data;do i=1 to &n;x=sqrt(-2*log(ranuni(&s)))*cos(8*atan2(1,1)*ranuni(&s));put x;end;run;%mend;

Con qualche spazio bianco:

%macro f(s, n);
    data;
        do i = 1 to &n;
            x = sqrt(-2 * log(ranuni(&s))) * cos(8 * atan2(1, 1) * ranuni(&s));
            put x;
        end;
    run;
%mend;

Questo definisce una macro che può essere chiamata come %f(5, 3). La macro esegue un passaggio di dati che scorre attraverso gli interi da 1 a N e ad ogni iterazione calcola una deviazione normale casuale usando Box-Muller e la stampa nel registro usando l' putistruzione.

SAS non ha built-in per pi, quindi il meglio che possiamo fare è approssimarlo con arctangent.

La ranuni()funzione (che è obsoleta ma richiede un paio di caratteri in meno rispetto alla funzione più recente) restituisce un numero casuale da una distribuzione uniforme. La documentazione SAS non fornisce molti dettagli sull'implementazione di RNG oltre a un periodo di 2 ^ 31-2.

Nelle macro SAS, alle variabili macro viene fatto riferimento con un precedente &e risolvono i loro valori in fase di esecuzione.

Come probabilmente hai visto, SAS è raramente un vero contendente in una gara di .


2

Java, 193 byte

Sebbene ciò non superi l'attuale leader Java, ho deciso di pubblicare comunque per mostrare un diverso metodo di calcolo. È una versione giocata a golf di OpenJDK nextGaussian().

class N extends java.util.Random{N(int s,int n){super(s);for(float a,v;n-->0;System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))for(a=0;a>=1|a==0;a=v*v+(v=2*nextFloat()-1)*v)v=2*nextFloat()-1;}}

Con interruzioni di riga:

class N extends java.util.Random{
    N(int s,int n){
        super(s);
        for(float a,v;
            n-->0;
            System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))
                for(a=0;
                    a>=1|a==0;
                    a=v*v+(v=2*nextFloat()-1)*v)v=2*nextFloat()-1;
    }
}

2
+1 per l'utilizzo di Marsaglia (o meglio per non utilizzare il semplice Box-Muller);)
Martin Ender

Questo non può essere un lambda? Qualcosa del tipo:(s,n)->{java.util.Random r=new java.util.Random(s);for(float a,v;n-->0;System.out.println(v*Math.sqrt(-2*Math.log(a)/a)))for(a=0;a>=1|a==0;a=v*v+(v=2*r.nextFloat()-1)*v)v=2*r.nextFloat()-1;}
Justin

2
@Quincunx Potrei, per un byte. Ma non mi piace nascondere le dichiarazioni delle mie funzioni in un codice non conteggiato, qualunque sia l'attuale consenso su meta. Vale la pena un byte per me;)
Geobits

2

T-SQL, 155 byte

CREATE PROC R(@S BIGINT,@N INT)AS
DECLARE @ INT=0,@K INT=8388607WHILE @<@N
BEGIN
SELECT SQRT(-2*LOG(RAND(@S*@%@K)))*COS(2*PI()*RAND(@S*9*@%@K))SET @+=1
END

Utilizzare con EXEC RS, N perché non esiste STD_IN in T-SQL dove S e N sono rispettivamente il seme e N. S produrrà sequenze "casuali" (RAND (seed) è una cattiva implementazione di numeri casuali) quando S> 2 ^ 16 (possibilmente prima, ma non lo garantirò). Utilizza Box-Muller come la maggior parte delle soluzioni finora. 8388607 è 2 ^ 23-1, che si spera dovrebbe generare 2 ^ 20 valori diversi.


2

Powershell, 164 byte

Param($s,$n)$q=2147483647
$a=GET-RANDOM -SETSEED $s
FOR(;$n---gt0;){$a=GET-RANDOM
$b=GET-RANDOM
[math]::SQRT(-2*[math]::LOG($a/$q))*[math]::COS(2*[math]::PI*$b/$q)}

Come la maggior parte delle risposte con Box-Muller. Non molto esperto con Powershell, quindi qualsiasi aiuto golf sarebbe apprezzato.


2

Rubino, 72 byte

->n,s{include Math;srand s;n.times{p sqrt(-2*log(rand))*sin(2*rand*PI)}}

Input (come funzione lambda):

f.(6, 12353405)

Produzione:

-1.1565142460805273
0.9352802655317097
1.3566720571574993
-0.9683973210257978
0.9851210877202192
0.14709635752306677

PS: vorrei sapere se questo può essere ulteriormente giocato a golf. Sono solo un principiante.


@ MartinBüttner Penso di aver usato troppa C in questi giorni. Totalmente dimenticato.
Zero Fiber

2

Matlab, 77

Il primo input dovrebbe essere n, il secondo s.

a=input('');
rand('seed',a(2));
for i=1:a;
    (-2*log(rand))^.5*cos(2*pi*rand)
end

2

Ottava, 91 96 88 byte

function r=n(s,n)rand("seed",s);x=rand(2,n);r=cos(2*pi*x(1,:)).*sqrt(-2*log(x(2,:)));end

Oppure, con spazi bianchi:

function r=n(s,n)
  rand("seed",s);
  x=rand(2,n);
  r=cos(2*pi*x(1,:)).*sqrt(-2*log(x(2,:)));
end

Metti il ​​seme in primo piano e usa il metodo Box-Mueller.

NB: Octave consente la generazione di array di numeri casuali e può utilizzare operazioni standard su questi array che producono output di array. L' .*operatore è la moltiplicazione elemento per elemento di due array per produrre il risultato.


Penso che questo non soddisfi le condizioni, se chiami n(0,1)e n(0,2)ricevi primi numeri diversi, vero?
Flawr

Merda, hai ragione. L'ho risolto ma mi è costato 5 byte ...
dcsohl

2

Pyth, 32 byte

Nessun Python viene ora utilizzato nelle virgolette a causa delle nuove funzioni che Pyth ha ora. Ancora un altro Box-Mueller.

 .xvzVQ*@_y.lOZ2.71 2.ty*3.14OZ1

Quello spazio all'inizio è importante.

.xvz             Seed RNG with evaluated input
VQ               For N in second input
*                Multiplication
 @       2       Square root
   _y            Times negative 2
    .l )         Natural log
     OZ          Of random float (RNG with zero give [0, 1) float)
 .t       1      Cosine from list of trig functions
  y              Double
   *             Multiplication
    .nZ          Pi from constants list
    OZ           Random Float

Il seeding non sembra funzionare nell'interprete online, ma funziona bene nella versione locale. L'interprete online sembra essere stato corretto, quindi ecco un permalink: permalink


1
Questo utilizza una funzionalità di Pyth ( .nZ) che non è stata implementata, quando è stata posta la domanda. (È stato effettivamente implementato oggi.) Pertanto questa risposta non dovrebbe far parte della competizione ( meta.codegolf.stackexchange.com/questions/4867/… ).
Jakube

K, tornerò alla soluzione a 32 caratteri
Maltysen

Sì, sarebbe meglio. Puoi ancora mostrare la tua nuova soluzione in una sezione separata della tua risposta. Ma il codice in competizione dovrebbe essere quello che funziona con il vecchio Pyth.
Jakube,

1
A proposito, non penso che neanche la soluzione 32 dovrebbe essere valida. Dal momento che utilizza il seme casuale inizializzato, che è stato aggiunto solo circa 5 giorni fa.
Jakube

1

STATA, 85 byte

di _r(s)_r(n)
set se $s
set ob $n
g a=sqrt(-2*ln(runiform()))*cos(2*runiform()*_pi)
l

Accetta input tramite standard (il primo numero è S, quindi N). Imposta il seme su S. Imposta il numero di osservazioni su N. Crea una variabile e imposta il suo valore sul valore di trasformazione Box Muller (grazie a @Alex per averlo mostrato). Quindi elenca tutte le osservazioni in una tabella con intestazione di colonna ae numeri di osservazione accanto a esse. Se questi non vanno bene, fammelo sapere e posso rimuovere le intestazioni e / o i numeri di osservazione.


1

R, 89 byte

So che R è stato fatto prima, ma volevo mostrare un approccio diverso rispetto al Box-Muller che tutti gli altri usavano. La mia soluzione utilizza il Teorema del limite centrale .

f=function(S,N){set.seed(S);a=1000;for(i in(1:N)){print(sqrt(12/a)*(sum(runif(a))-a/2))}}

1
Temo che il teorema del limite centrale non soddisfi "l'algoritmo scelto deve produrre una distribuzione normale teoricamente esatta". Indipendentemente dal numero di variabili uniformi aggiunte, purché la somma sia finita, la distribuzione normale sarà sempre approssimativa. (Mentre il teorema del limite centrale è una buona idea, ho dovuto escluderlo proprio perché non è chiaro quale valore debba essere usato anel tuo codice in modo tale che il risultato sia "giusto".)
Martin Ender

1
Ne è valsa la pena;)
Michal,

1

TI-Basic, 74 byte

Prompt S,N:S→rand:For(X,1,N:0→A:0→V:0→W:While A≥1 or A=0:2rand-1→V:2rand-1→W:V²+W²→A:End:Disp VW√(Aֿ¹-2log(A:End

1      1111111   11   1111111111111111111     1111   111111   1111111   11111111111111  11    111111111   111

In ¹realtà è l'operatore inverso.


1

Perl, 150 108 107 byte

Questo utilizza il metodo polare Marsaglia . Chiamato con f (S, N).

Spostato il compito di $anel calcolo di $c.

107:

sub f{srand$_[0];map{do{$c=($a=-1+2*rand)**2+(-1+2*rand)**2}until$c<1;print$a*sqrt(-2*log($c)/$c)}1..$_[1]}

Rimossa la memoria dei numeri di riserva e la definizione di $b.

108:

sub f{srand$_[0];map{do{$a=-1+2*rand,$c=$a**2+(-1+2*rand)**2}until$c<1;print$a*sqrt(-2*log($c)/$c)}1..$_[1]}

150:

sub f{srand$_[0];map{$h?$h=!print$s:do{do{$a=-1+2*rand,$b=-1+2*rand,$c=$a*$a+$b*$b}until$c<1;$d=sqrt(-2*log($c)/$c);$s=$b*$d;$h=print$a*$d;}}1..$_[1]}

1

Swift, 144 142

Niente di intelligente, visto solo come funziona Swift.

import Foundation;func r(s:UInt32,n:Int){srand(s);for i in 0..<n{println(sqrt(-2*log(Double(rand())/0xffffffff))*sin(2*Double(rand())*M_PI))}}

Speravo di poter usare (0 ... n) .map {} ma il compilatore non sembra riconoscere la mappa {} a meno che tu non usi un parametro.


ovviamente...? èforEach se non vuoi un valore di ritorno, e sono abbastanza sicuro che _ insia obbligatorio
solo ASCII il

che succede /0xffffffffa proposito
solo ASCII il

1

Haskell , 97 byte

import System.Random
h(a:b:c)=sqrt(-2*log a::Float)*cos(2*pi*b):h c
f a=take a.h.randoms.mkStdGen

Provalo online!

Solo la tua trasformazione Box-Muller di base, in un infinito elenco di numeri casuali.


1

Python 3 , 118 byte

from random import*
from math import*
def f(s,n):seed(s);return[sqrt(-2*log(random()))*cos(tau*random())for _ in[0]*n]

Provalo online!


0

SmileBASIC, 81 byte

Bene, ora che ho risposto alla prima domanda, devo fare tutto il resto ...

Generazione di numeri casuali è a buon mercato, ma semina il RNG utilizza la più lunga funzione built-in lingua, RANDOMIZE.

DEF N S,N
RANDOMIZE.,S
FOR I=1TO N?SQR(-2*LOG(RNDF()))*COS(PI()*2*RNDF())NEXT
END

Forse c'è un modo per ottimizzare la formula. Non vedo come sia necessario utilizzare due chiamate RNG.


Si è richiesto di avere due campioni indipendenti per la trasformazione di Box-Muller
ASCII-only
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.