Golf ngẫu nhiên trong ngày # 2: Số từ phân phối bình thường


12

Giới thiệu về bộ

Trước hết, bạn có thể coi điều này giống như bất kỳ thử thách chơi gôn mã nào khác, và trả lời nó mà không phải lo lắng về loạt bài này. Tuy nhiên, có một bảng xếp hạng trên tất cả các thách thức. Bạn có thể tìm thấy bảng xếp hạng cùng với một số thông tin khác về loạt bài trong bài đầu tiên .

Mặc dù tôi có một loạt các ý tưởng được xếp hàng cho loạt bài này, những thách thức trong tương lai vẫn chưa được đặt ra. Nếu bạn có bất kỳ đề xuất nào, xin vui lòng cho tôi biết trên bài đăng hộp cát có liên quan .

Lỗ 2: Số từ phân phối chuẩn

Tôi không thể tin rằng điều này chưa được thực hiện! Bạn đang tạo số ngẫu nhiên, rút ​​ra từ một phân phối bình thường . Một số quy tắc (phần lớn trong số chúng có thể được tự động bao phủ bởi hầu hết các lần gửi, nhưng một số trong số chúng được áp dụng để đảm bảo tính thống nhất của kết quả giữa các ngôn ngữ khác nhau):

  • Bạn nên lấy hai số nguyên không âm làm đầu vào : một hạt giống Svà số Nlượng để trả về. Đầu ra phải là một danh sách các số Ndấu phẩy động, được rút ra từ một phân phối bình thường với giá trị trung bình 0phương sai 1 . Bất cứ khi nào trình của bạn được đưa ra cùng một hạt giống, Snó sẽ tạo ra cùng một số. Cụ thể, nếu nó được gọi một lần với và một lần với , các mục đầu tiên của hai đầu ra phải giống hệt nhau. Ngoài ra, ít nhất 2 16 giá trị khác nhau sẽ tạo ra các chuỗi khác nhau.(S, N1)(S, N2)min(N1, N2)S

  • Bạn có thể sử dụng bất kỳ trình tạo số ngẫu nhiên tích hợp nào được ghi lại để rút số từ phân phối thống nhất (xấp xỉ) , miễn là bạn có thể chuyển Ssang nó và nó hỗ trợ ít nhất 2 16 hạt khác nhau. Nếu bạn làm như vậy, RNG sẽ có thể trả về ít nhất 2 20 giá trị khác nhau cho bất kỳ số nào bạn yêu cầu từ nó.

  • Nếu thống nhất RNG có sẵn của bạn có một phạm vi nhỏ hơn, không phải là seedable, hoặc hỗ trợ quá ít hạt giống, bạn phải đầu tiên xây dựng một RNG thống nhất với một loạt đủ lớn trên đỉnh được xây dựng trong một hoặc bạn phải thực hiện của riêng bạn RNG phù hợp sử dụng hạt giống. Trang này có thể hữu ích cho việc đó.
  • Nếu bạn không triển khai thuật toán đã thiết lập để tạo phân phối bình thường, vui lòng bao gồm bằng chứng về tính chính xác. Trong cả hai trường hợp, thuật toán bạn chọn phải mang lại phân phối chuẩn chính xác về mặt lý thuyết (hạn chế các loại dữ liệu PRNG cơ bản hoặc giới hạn chính xác).
  • Việc triển khai của bạn nên sử dụng và trả về các số có dấu phẩy động (rộng tối thiểu 32 bit) hoặc các số điểm cố định (rộng tối thiểu 24 bit) và tất cả các phép toán số học nên sử dụng toàn bộ chiều rộng của loại đã chọn.
  • Bạn không được sử dụng bất kỳ hàm dựng sẵn nào liên quan trực tiếp đến phân phối bình thường hoặc tích phân Gaussian, như hàm Error hoặc nghịch đảo của nó.

Bạn có thể viết một chương trình đầy đủ hoặc một hàm và nhận đầu vào thông qua STDIN, đối số dòng lệnh, đối số chức năng hoặc lời nhắc và tạo đầu ra thông qua giá trị trả về hoặc bằng cách in ra STDOUT (hoặc thay thế gần nhất).

SNsẽ là các số nguyên không âm, mỗi số nhỏ hơn 2 20 . Đầu ra có thể ở bất kỳ định dạng chuỗi hoặc danh sách thuận tiện, rõ ràng.

Đây là mã golf, vì vậy bài nộp ngắn nhất (tính bằng byte) sẽ thắng. Và tất nhiên, lần gửi ngắn nhất cho mỗi người dùng cũng sẽ tham gia vào bảng xếp hạng tổng thể của loạt bài.

Bảng xếp hạng

Bài đầu tiên của loạt bài tạo ra một bảng thành tích.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu mọi câu trả lời bằng tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh chúng qua. Ví dụ:

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

(Ngôn ngữ hiện không được hiển thị, nhưng đoạn mã yêu cầu và phân tích cú pháp, và tôi có thể thêm bảng xếp hạng ngôn ngữ trong tương lai.)


Đợi đã, chúng ta có được phép sử dụng RNG không phạm vi không?
mniip

Các câu trả lời hiện có của PS 2 dường như sử dụng [0, 1) RNG dấu phẩy động, điều này có được phép không?
mniip

@mniip Có, RNG của dấu phẩy động được cho phép, miễn là chúng đồng nhất, có thể gieo hạt và có thể trả về số lượng phao nổi khác nhau cần thiết.
Martin Ender

Câu trả lời:


8

APL Dyalog, 33 byte

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

Hộp-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)

Tôi khá chắc chắn rằng điều này không thể bị đánh bại bởi bất kỳ ngôn ngữ khác.
Zero Fiber

2
Điều này không đáp ứng quy tắc này: "Đặc biệt, nếu nó được gọi một lần với (S, N1) và một lần với (S, N2), các mục nhập đầu tiên (N1, N2) của hai đầu ra phải giống hệt nhau."
bến tàu

@marinus Cảm ơn, đã sửa. Tôi cũng thay đổi ⎕rlđược S+1⎕rl←0có ý nghĩa đặc biệt.
ngn 8/2/2015

Bạn có thể không thực sự cần +1, tất cả những gì nó nói là bạn cần hỗ trợ ít nhất 2 ^ 16 giá trị khác nhau. Vì vậy, làm việc chính xác trong phạm vi [1..2 ^ 16] sẽ ổn.
bến tàu

S = 0 sẽ làm cho việc tính toán không lặp lại, vi phạm quy tắc bạn đã trích dẫn ở trên.
ngn 8/2/2015

8

R, 68 byte

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

Điều này sử dụng runif()hàm, tạo ra các độ lệch ngẫu nhiên từ một phân phối đồng đều. Hạt giống để tạo số ngẫu nhiên được chỉ định bằng cách sử dụng set.seed(), theo mặc định, sử dụng thuật toán Mersenne-Twister với khoảng thời gian 2 ^ 19937-1.

Kết quả là một vectơ R có độ dài N chứa các độ lệch chuẩn chuẩn được tính toán.

Phương pháp này sử dụng phương pháp Box-Muller: Đối với hai biến ngẫu nhiên thống nhất độc lập U và V, nhập mô tả hình ảnh ở đây


Nếu đó là cú pháp hợp lệ trong R, bạn có thể bỏ qua f=(hàm không nhất thiết phải được đặt tên, nếu các hàm không tên là một thứ trong ngôn ngữ của bạn).
Martin Ender

@ MartinBüttner: Tôi đánh giá cao đề xuất này nhưng theo hiểu biết của tôi thì R sẽ không biết phải làm gì với một chức năng không tên.
Alex A.

Tôi luôn nhận được thông báo lỗi Error: unexpected '}' in "f=fu...bên cạnh, bạn có chắc chắn nhận được các số đầu tiên giống nhau nếu bạn gọi f(0,1)f(0,2)không?
flawr 6/2/2015

4

Thuốc nhuộm APL, 42 34

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

Đây là một hàm lấy Sđối số bên trái và Nđối số bên phải của nó.

     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

Đây là một triển khai của biến đổi Box-Muller, sử dụng toán tử ngẫu nhiên tích hợp sẵn của Dyalog APL ? , theo mặc định là một twister Mersenne trả về các giá trị 64 bit, là đủ.

Giải trình:

  • ⎕RL←⍺: đặt hạt giống ngẫu nhiên thành .
  • ?⍵2⍴0: tạo các cặp số ngẫu nhiên trong khoảng từ 0 đến 1.
  • {... }/: áp dụng chức năng sau cho mỗi cặp:
    • (.5*⍨¯2×⍟⍺)×1○⍵×○2: tính Z0giá trị ( sqrt(-2 ln ⍺)×cos(2π⍵)).

1
Trong v14.0 ?0trả về số dấu phẩy động trong khoảng từ 0 đến 1.
ngn

3

Perl, 67

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

Box-Muller như trong các mục khác. flấy tham số theo thứ tựS, N .

Sử dụng:

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

Điều này nhận đầu vào thông qua chức năng và đầu ra thông qua thiết bị xuất chuẩn. Nó sử dụng phương pháp Box-Muller.


5
s=0;s++<n;-> ;n-->0;?
Geobits 6/2/2015

1
@Geobits Trông giống như một lambda: D
TheNumberOne 6/2/2015

3

Hàng hóa 64 cơ bản, 76 70 63 byte

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

Do bộ ký tự PETSCII chứa một số ký hiệu không có trong Unicode, tôi đã thực hiện thay thế: /= SHIFT+N, = SHIFT+O, = SHIFT+Q, = SHIFT+I, =SHIFT+E

Điều này thực hiện biến đổi Box-Muller tiêu chuẩn để tạo ra các số; Tôi đã chọn sin (x) một nửa của biến đổi vì Commodore 64 Basic có lối tắt hai ký tự cho sin(), nhưng không phải cho cos().

Mặc dù hướng dẫn sử dụng có quy định khác, giá trị của đối số RND không thành vấn đề: nếu một số âm được thông qua, trình tạo số ngẫu nhiên không chỉ đơn thuần là được gieo lại, nó được ghép lại với số đó . Điều này làm cho việc gieo hạt đơn giản hơn nhiều: thay vì cần đến POKEnăm vị trí bộ nhớ, tôi chỉ cần thực hiện một cuộc gọi không làm gì cảRND , điều này làm giảm mã từ hai dòng / 121 byte xuống 1 dòng / 76 byte.

Chỉnh sửa: Giảm sáu byte bằng cách nhận ra tôi có thể kết hợp hai INPUTcâu lệnh và khoảng trống sau TOlà tùy chọn.

Chỉnh sửa: Thực tế đã đánh bại bảy người khác: Trên thực tế, Commodore Basic thực sự có Pi là một hằng số tích hợp và thậm chí nó có thể đánh máy trên bàn phím hiện đại ( SHIFT+PgDntrong trường hợp bạn đang tự hỏi).


3

Mã máy 80386, 72 byte

Mã thập phân của mã:

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

Đây là mã nguồn (có thể được Visual Studio biên dịch):

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

Ở đây tôi sử dụng trình tạo số ngẫu nhiên aa Lehmer . Nó sử dụng thuật toán sau:

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

Ở đây 4294967291 là một số nguyên tố lớn (2 ^ 32-5) và 116 là một số nhỏ (nhỏ hơn 128; xem bên dưới) là gốc nguyên thủy của nó . Tôi đã chọn một gốc nguyên thủy có phân phối ngẫu nhiên ít nhiều ngẫu nhiên và các số nguyên trong biểu diễn nhị phân (01110100). RNG này có thời gian tối đa có thể là 4294967290, nếu hạt giống là khác không.


Các số tương đối nhỏ tôi đã sử dụng ở đây (116 và 4294967291, có thể được biểu thị bằng -5) cho phép tôi tận dụng leamã hóa lệnh:

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

Nó được lắp ráp thành 3 byte nếu các số có thể vừa với 1 byte.


Phép nhân và phép chia sử dụng edxeaxnhư các thanh ghi làm việc của chúng, đó là lý do tại sao tôi tạo seedtham số thứ hai cho hàm ( fastcallgọi quy ước sử dụng edxđể truyền tham số thứ hai). Ngoài ra, tham số đầu tiên được truyền vào ecx, đây là nơi tốt để giữ bộ đếm: một vòng lặp có thể được tổ chức trong 1 lệnh!

e2 c6        loop myloop

Để chuyển đổi một số nguyên thành số dấu phẩy động, tôi đã khai thác biểu diễn các số dấu phẩy động có độ chính xác đơn: nếu tôi đặt 9 bit cao (số mũ) thành mẫu bit 001111111và để ngẫu nhiên 23 bit thấp, tôi sẽ nhận được một số ngẫu nhiên trong phạm vi 1 ... 2. Tôi lấy ý tưởng từ đây . Để đặt 9 bit cao, tôi đã sử dụng một số thao tác bit 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

Để tạo hai số ngẫu nhiên, tôi đã sử dụng một vòng lặp lồng nhau gồm 2 lần lặp. Tôi đã tổ chức nó với xor:

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

Mã dấu phẩy động thực hiện biến đổi 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

Ví dụ sử dụng:

*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]

Kiểu trả về của randombị ràng buộc Float, điều này randomtạo ra một số float đồng nhất trong [0, 1). Từ đó trở đi, đó là một công thức chế tạo hộp simlpe với một số phép thuật vô nghĩa để tạo danh sách.


2

Golflua, 63 70

Thông tin và hướng dẫn của Golflua.

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

Trả về một bảng chứa các giá trị. Trong ví dụ tôi đang sử dụng ~T.u( ), giống như return table.unpack( )trong 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

Rất nhiều ký tự đã được lưu bằng cách đặt môi trường của hàm thành M(aka math).


2

SÀI GÒN, 108

Tôi đã đăng một câu trả lời trong R ngắn hơn thế này, nhưng có rất ít câu trả lời của SAS trên PPCG, vậy tại sao không thêm câu trả lời khác?

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

Với một số khoảng trắng:

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

Điều này định nghĩa một macro có thể được gọi là như thế %f(5, 3). Macro thực thi một bước dữ liệu lặp qua các số nguyên từ 1 đến N và tại mỗi lần lặp, nó tính toán độ lệch bình thường ngẫu nhiên bằng cách sử dụng Box-Muller và in nó vào nhật ký bằng cách sử dụngput câu lệnh.

SAS không tích hợp sẵn cho pi, vì vậy điều tốt nhất chúng ta có thể làm là ước tính nó với arctangent.

Các ranuni() chức năng (mà bị phản đối nhưng đòi hỏi một vài nhân vật ít hơn các chức năng mới hơn) trả về một số ngẫu nhiên từ một phân bố đều. Tài liệu của SAS không cung cấp nhiều thông tin chi tiết về việc triển khai RNG ngoài việc nó có thời gian 2 ^ 31-2.

Trong các macro SAS, các biến macro được tham chiếu trước &và giải quyết các giá trị của chúng trong thời gian chạy.

Như bạn có thể đã chứng kiến, SAS hiếm khi là một ứng cử viên thực sự trong một cuộc thi .


2

Java, 193 byte

Trong khi điều này không đánh bại nhà lãnh đạo Java hiện tại, tôi vẫn quyết định đăng bài để hiển thị một phương pháp tính toán khác. Đây là phiên bản chơi gôn của 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;}}

Với ngắt dòng:

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 khi sử dụng Marsaglia (hay đúng hơn là không sử dụng Box-Muller thẳng tiến);)
Martin Ender

Đây có thể không phải là một lambda? Một cái gì đó như:(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 Tôi có thể, cho một byte. Nhưng tôi không thích che giấu các khai báo hàm của mình trong mã không đếm được, bất kể sự đồng thuận hiện tại về meta về nó. Nó đáng giá một byte đối với tôi;)
Geobits 7/2/2015

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

Sử dụng với EXEC RS, N vì không có STD_IN trong T-SQL trong đó S và N lần lượt là hạt giống và N. S sẽ tạo ra chuỗi "ngẫu nhiên" (RAND (hạt giống) là một chuỗi thực hiện số ngẫu nhiên thực sự tồi tệ) khi S> 2 ^ 16 (có thể trước đó, nhưng tôi sẽ không đảm bảo điều đó). Sử dụng Box-Muller giống như hầu hết các giải pháp cho đến nay. 8388607 là 2 ^ 23-1, hy vọng sẽ tạo ra 2 ^ 20 giá trị khác nhau.


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

Giống như hầu hết các câu trả lời với Box-Muller. Không có nhiều kinh nghiệm với Powershell, vì vậy bất kỳ trợ giúp chơi gôn nào cũng sẽ được đánh giá cao.


2

Ruby, 72 byte

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

Đầu vào (dưới dạng hàm lambda):

f.(6, 12353405)

Đầu ra:

-1.1565142460805273
0.9352802655317097
1.3566720571574993
-0.9683973210257978
0.9851210877202192
0.14709635752306677

PS: Tôi muốn biết nếu điều này có thể được chơi gôn hơn nữa. Tôi chỉ là người mới bắt đầu.


@ MartinBüttner Tôi nghĩ rằng tôi đã sử dụng quá nhiều C những ngày này. Hoàn toàn quên mất.
Zero Fiber

2

Matlab, 77

Đầu vào đầu tiên phải là n, đầu vào thứ hai s.

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

2

Octave, 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

Hoặc, với khoảng trắng:

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

Đặt hạt giống lên phía trước và sử dụng phương pháp Box-Mueller.

Lưu ý: Octave cho phép tạo ra các mảng số ngẫu nhiên và có thể sử dụng các thao tác chuẩn trên các mảng này tạo ra các đầu ra mảng. Các .*nhà điều hành là yếu tố-by-yếu tố nhân của hai mảng để tạo ra kết quả.


Tôi nghĩ rằng điều này không đáp ứng các điều kiện, nếu bạn gọi n(0,1)n(0,2)bạn nhận được các số đầu tiên khác nhau, phải không?
flawr 6/2/2015

Tào lao, bạn đúng. Tôi đã sửa nó nhưng nó tốn của tôi 5 byte ...
dcsohl

2

Bình thường, 32 byte

Hiện tại không có Python nào được sử dụng trong siêu trích dẫn vì các chức năng mới mà Pyth hiện có. Một hộp Mueller khác.

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

Không gian đó trong đầu là quan trọng.

.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

Seeding dường như không hoạt động trong trình thông dịch trực tuyến, nhưng nó hoạt động tốt trong phiên bản địa phương. Trình thông dịch trực tuyến dường như đã được sửa, vì vậy đây là một permalink: permalink


1
Điều này sử dụng một tính năng của Pyth ( .nZ) chưa được triển khai khi câu hỏi được đặt ra. (Nó thực sự đã được thực hiện ngày hôm nay.) Vì vậy, câu trả lời này không nên là một phần của cuộc thi ( meta.codegolf.stackexchange.com/questions/4867/ Lỗi ).
Jakube

K, tôi sẽ quay lại giải pháp 32 char
Maltysen

Vâng, điều đó sẽ tốt hơn. Bạn vẫn có thể hiển thị cho bạn giải pháp mới trong phần riêng biệt của câu trả lời của bạn. Nhưng mã thi đấu của bạn phải là mã làm việc với Pyth cũ.
Jakube

1
Btw, tôi không nghĩ rằng giải pháp 32 nên hợp lệ. Vì nó sử dụng hạt giống ngẫu nhiên được khởi tạo, chỉ mới được thêm vào khoảng 5 ngày trước.
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

Đưa đầu vào qua tiêu chuẩn trong (số đầu tiên là S, sau đó là N). Đặt hạt giống thành S. Đặt số lượng quan sát thành N. Tạo một biến và đặt giá trị của nó thành giá trị biến đổi Box Muller (nhờ @Alex để hiển thị nó). Sau đó liệt kê tất cả các quan sát trong một bảng có tiêu đề cột a và các số quan sát bên cạnh chúng. Nếu những điều này không ổn, hãy cho tôi biết và tôi có thể xóa các tiêu đề và / hoặc số quan sát.


1

R, 89 byte

Tôi biết R đã được thực hiện trước đây nhưng tôi muốn thể hiện một cách tiếp cận khác với Box-Muller mà mọi người khác đã sử dụng. Giải pháp của tôi sử dụng Định lý giới hạn trung tâm .

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

1
Tôi e rằng, định lý giới hạn trung tâm không thỏa mãn "thuật toán bạn chọn phải mang lại phân phối chuẩn chính xác về mặt lý thuyết". Cho dù bạn thêm bao nhiêu biến thống nhất, miễn là tổng là hữu hạn, phân phối chuẩn sẽ luôn gần đúng. (Mặc dù định lý giới hạn trung tâm là một ý tưởng hay, tôi đã phải loại trừ chính xác vì không rõ giá trị nào nên được sử dụng choa mã của bạn sao cho kết quả là "công bằng".)
Martin Ender

1
Đó là giá trị một shot;)
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

Đây ¹thực sự là toán tử nghịch đảo.


1

Perl, 150 108 107 byte

Điều này sử dụng Phương pháp cực Marsaglia . Được gọi với f (S, N).

Đã chuyển nhượng $a thành tính toán của $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]}

Loại bỏ lưu trữ số dự phòng và định nghĩa của $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

Không có gì thông minh, chỉ cần nhìn cách Swift hoạt động.

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

Tôi đã hy vọng tôi có thể sử dụng (0 ... n) .map {} nhưng trình biên dịch dường như không nhận ra bản đồ {} trừ khi bạn sử dụng tham số.


tất nhiên...? đó làforEach nếu bạn không muốn có một giá trị trả về, và tôi khá chắc chắn rằng _ inlà bắt buộc
ASCII chỉ

những gì /0xffffffffcho btw
ASCII

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

Hãy thử trực tuyến!

Chỉ cần chuyển đổi Box-Muller cơ bản của bạn, trên một danh sách vô số các số ngẫu nhiên.



0

SmileBASIC, 81 byte

Chà, bây giờ tôi đã trả lời câu hỏi đầu tiên, tôi phải làm tất cả phần còn lại ...

Tạo số ngẫu nhiên là rẻ, nhưng việc tạo RNG sử dụng hàm dựng sẵn dài nhất trong ngôn ngữ , RANDOMIZE.

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

Có lẽ có một số cách để tối ưu hóa công thức. Tôi không thấy cách sử dụng hai cuộc gọi RNG.


cần thiết để có hai mẫu độc lập cho việc chuyển đổi Box-Muller
ASCII chỉ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.