Випадковий гольф дня №2: Номери від звичайного розповсюдження


12

Про серію

По-перше, ви можете ставитися до цього, як і до будь-якого іншого виклику коду для гольфу, і відповідати на нього, не турбуючись про серію взагалі. Однак існує лідери у всіх викликах. Ви можете знайти таблицю лідерів разом з додатковою інформацією про серії в першій публікації .

Хоча у мене є маса ідей, що вибудовуються для цієї серії, майбутні виклики ще не поставлені в камені. Якщо у вас є якісь пропозиції, будь ласка, повідомте мене про це у відповідній поштовій скриньці .

Отвір 2: Числа від нормального розподілу

Я не можу повірити, що цього ще не було зроблено! Ви повинні генерувати випадкові числа, виходячи із звичайного розподілу . Деякі правила (більшість із них, ймовірно, автоматично охоплюються більшістю подань, але деякі з них існують для забезпечення узгодженості результатів між різними мовами):

  • Ви повинні взяти два невід’ємні цілі числа як вхідні дані : насіння Sта кількість Nчисел, які потрібно повернути. На виході повинен бути список Nчисел з плаваючою комою, виведений із звичайного розподілу із середнім значенням 0 та дисперсією 1 . Щоразу, коли ваші подання даються однаковим насінням, Sвін повинен давати однакову кількість. Зокрема, якщо він викликається один раз з і один раз з , перші записи двох виходів повинні бути однаковими. Крім того, щонайменше 2 16 різних значень повинні виробляти різні послідовності.(S, N1)(S, N2)min(N1, N2)S

  • Ви можете використовувати будь-який вбудований генератор випадкових чисел, який задокументований для отримання чисел із (приблизно) рівномірного розподілу, за умови, що ви можете передати Sйого та підтримує щонайменше 2 16 різних насінин. Якщо це зробити, RNG повинен мати можливість повернути щонайменше 2 20 різних значень для будь-якого заданого вами номера.

  • Якщо наявний рівномірний СПГ має менший діапазон, не піддається посіву, або підтримує занадто мало насіння, ви повинні спочатку створити рівномірний СПГ з достатньо великим діапазоном поверх вбудованого або потрібно реалізувати свій власний відповідний RNG за допомогою насіння. Ця сторінка може бути корисною для цього.
  • Якщо ви не реалізуєте встановлений алгоритм для генерації нормальних розподілів, будь ласка, додайте доказ коректності. У будь-якому випадку алгоритм, який ви вибрали, повинен дати теоретично точний нормальний розподіл (обмеження обмеження базових типів PRNG або обмежене точність даних).
  • Ваша реалізація повинна використовувати або повертати числа з плаваючою комою (принаймні 32 біта в ширину) або номери з фіксованою точкою (принаймні 24 біт шириною), і всі арифметичні операції повинні використовувати повну ширину обраного типу.
  • Ви не повинні використовувати будь-які вбудовані функції, безпосередньо пов'язані з нормальним розподілом або гауссовими інтегралами, як-от функція Error або її зворотна.

Ви можете написати повну програму або функцію та взяти введення через STDIN, аргумент командного рядка, аргумент функції або підказку та отримати висновок через повернене значення або надрукувавши STDOUT (або найближчу альтернативу).

Sі Nбудуть невід’ємними цілими числами, кожне менше 2 20 . Вихід може бути у будь-якому зручному, однозначному списку чи рядковому форматі.

Це код гольфу, тому виграє найкоротше подання (у байтах). І звичайно, найкоротше подання на кожного користувача також увійде в загальну таблицю лідерів серії.

Таблиця лідерів

Перший пост серії генерує таблицю лідерів.

Щоб відповіді відображалися, почніть кожну відповідь із заголовка, використовуючи такий шаблон Markdown:

# Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

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

(Мова наразі не відображається, але фрагмент вимагає і проаналізувати його, і я можу в майбутньому додати таблицю лідерів за мовою.)


Зачекайте, чи дозволено нам використовувати RNG без цілого числа?
mniip

PS 2 існуючі відповіді, здається, використовують [0, 1) RNG з плаваючою точкою, чи це дозволено?
mniip

@mniip Так, RNG з плаваючою точкою дозволені, за умови, що вони є рівномірними, засівними та здатними повертати необхідну кількість чітко поплавців.
Мартін Ендер

Відповіді:


8

Діалог APL, 33 байти

{(.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)

Я впевнений, що це не може побороти жодна інша мова.
Нульове волокно

2
Це правило не відповідає: "Зокрема, якщо він викликається один раз із (S, N1) та один раз з (S, N2), перші записи (2, N2) двох виходів повинні бути однаковими."
Марін

@marinus Спасибі, виправлено. Я також змінив ⎕rlбути S+1тому , що ⎕rl←0має особливе значення.
ngn

Вам, мабуть, насправді не потрібні +1, все говорить, що вам потрібно підтримувати принаймні 2 ^ 16 різних значень. Отже, працюючи правильно в діапазоні [1..2 ^ 16], повинно бути нормально.
marinus

S = 0 зробить обчислення не повторюваними, що порушує правило, яке ви цитували вище.
ngn

8

R, 68 байт

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

При цьому використовується runif()функція, яка генерує випадкові відхилення від рівномірного розподілу. Насіння для генерації випадкових чисел задається за допомогою set.seed(), яке за замовчуванням використовує алгоритм Мерсенна-Твістера з періодом 2 ^ 19937-1.

В результаті виходить R-вектор довжини N, що містить обчислені стандартні нормальні відхилення.

Для цього використовується метод Box-Muller: Для двох незалежних рівномірних випадкових величин U і V, введіть тут опис зображення


Якщо це правильний синтаксис у R, ви можете залишити його f=(функцію не обов’язково потрібно називати, якщо неназвані функції є предметом вашої мови).
Мартін Ендер

@ MartinBüttner: Я ціную пропозицію, але, наскільки мені відомо, R не знав би, що робити з неназваною функцією.
Олексій А.

Крім того, я завжди отримую повідомлення про помилку Error: unexpected '}' in "f=fu..., ви впевнені, що отримуєте однакові перші номери, якщо дзвоните f(0,1)і f(0,2)?
недолік

4

Діялог АПЛ, 42 34

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

Це функція, яка приймає Sяк лівий аргумент і 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

Це реалізація перетворення Box-Muller, використовуючи вбудований випадковий оператор Dyalog APL ?, який за замовчуванням являє собою твістер Mersenne, який повертає 64-бітні значення, яких має бути достатньо.

Пояснення:

  • ⎕RL←⍺: встановити випадкове насіння на .
  • ?⍵2⍴0: генерують пари випадкових чисел між 0 і 1.
  • {... }/: застосувати наступну функцію до кожної пари:
    • (.5*⍨¯2×⍟⍺)×1○⍵×○2: обчислити Z0значення ( sqrt(-2 ln ⍺)×cos(2π⍵)).

1
У v14.0 ?0повертається число з плаваючою комою між 0 і 1.
ngn

3

Перл, 67

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

Box-Muller, як і в інших записах. fприймає параметри в порядку S, N.

Використання:

$ 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 байт

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

Це вимагає введення через функцію та виведення через stdout. Він використовує метод Box-Muller.


5
s=0;s++<n;-> ;n-->0;?
Геобіт

1
@Geobits Виглядає як лямбда: D
TheNumberOne

3

Commodore 64 Basic, 76 70 63 байт

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

Оскільки набір символів PETSCII містить деякі символи, відсутні в Unicode, я здійснив підстановку: /= SHIFT+N, = SHIFT+O, = SHIFT+Q, = SHIFT+I, =SHIFT+E

Це реалізує стандартне перетворення Box-Muller для створення чисел; Я вибрав sin (x) половину перетворення, оскільки Commodore 64 Basic має двосимвольний ярлик для sin(), але не для cos().

Хоча в посібнику зазначено інакше, значення аргументу RND має значення: якщо передається негативне число, генератор випадкових чисел не просто повторно висівається, він повторно засівається цим числом . Це робить насіння набагато простішим: замість того, щоб потребувати POKEп'яти місць пам'яті, мені просто потрібно зробити дзвінок без нічого RND, що зменшує код з двох рядків / 121 байт до 1 рядка / 76 байт.

Редагувати: Гольф вийшов на шість байтів, зрозумівши, що я можу поєднати два INPUTтвердження, і що пробіл після цього TOбув необов’язковий

Редагувати: Golfed ще семеро: Commodore Basic насправді має Pi як вбудовану константу, і це навіть можна набрати на сучасній клавіатурі ( SHIFT+PgDnна випадок, коли вам було цікаво).


3

80386 код машини, 72 байти

Шестнадцятковий код:

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

Ось вихідний код (може бути скомпільований 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;
    }
}

Тут я використовую генератор випадкових чисел Леамера . Тут використовується наступний алгоритм:

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

Тут 4294967291 - велике (2 ^ 32-5) просте число, а 116 - невелике (менше 128; див. Нижче) число, яке є його примітивним коренем . Я вибрав примітивний корінь, який має більш-менш випадковий розподіл нулів та одиниць у двійковому поданні (01110100). Цей РНГ має максимально можливий період 4294967290, якщо насіння є нульовим.


Порівняно невеликі числа, які я тут використав (116 та 4294967291, які можна представити також як -5), дозволяють скористатися leaкодуванням інструкцій:

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

Він збирається в 3 байти, якщо числа можуть вміщуватися в 1 байт.


Множення та ділення використовують edxі eaxяк їх робочі регістри, саме тому я зробив seedдругий параметр функції ( fastcallвиклик конвенції використовує edxдля передачі другого параметра). Крім того, передається перший параметр ecx, який є хорошим місцем для проведення лічильника: цикл може бути організований за 1 інструкцією!

e2 c6        loop myloop

Щоб перетворити ціле число в число з плаваючою комою, я скористався поданням одноточних чисел з плаваючою комою: якщо я встановив високі 9 біт (показник) на бітову схему 001111111, а 23 низьких біта залиште випадковим, я отримати випадкове число в діапазоні 1 ... 2. Я взяв ідею звідси . Щоб встановити високі 9 біт, я використав декілька бітів 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

Для генерації двох випадкових чисел я використав вкладений цикл з 2 ітерацій. Я організував це за допомогою xor:

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

Код з плаваючою комою реалізує перетворення Box-Muller .


2

Хаскелл, 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

Приклад використання:

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

Тип повернення randomобмежений Float, що змушує randomгенерувати рівномірний поплавок у [0, 1). Відтепер це формула simlpe box-muller з якоюсь безглуздою магією для створення списку.


2

Гольфлуа, 63 70

Інформація та інструкції Golflua.

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

Повертає таблицю, що містить значення. У прикладі, який я використовую ~T.u( ), такий самий, як return table.unpack( )у луа.

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

Багато знаків було збережено, встановивши середовище функції M(ака math).


2

SAS, 108

Я вже опублікував відповідь на R, яка коротша за цю, але на PPCG відповідей дуже мало, тому чому б не додати ще одну?

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

З пробілом:

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

Це визначає макрос, який можна назвати подібним %f(5, 3). Макрос виконує етап даних, який проходить через цілі числа 1 до N, і при кожній ітерації він обчислює випадкове нормальне відхилення за допомогою Box-Muller і друкує його в журнал за допомогою putоператора.

SAS не має вбудованого для pi, тому найкраще, що ми можемо зробити, це наблизити його до арктангенту.

ranuni()Функція (яка схвалюється , але потрібно трохи менше символів , ніж нова функція) повертає випадкове число з рівномірного розподілу. Документація SAS не містить багато деталей щодо впровадження RNG, крім періоду 2 ^ 31-2.

У макросах SAS макро змінних посилаються на попередні &і визначаються їх значеннями під час виконання.

Як ви, напевно, були свідками, SAS рідко є фактичним суперником у змаганні з .


2

Java, 193 байт

Хоча це не перемагає поточного лідера Java, я все-таки вирішив опублікувати, щоб показати інший метод обчислення. Це гольф-версія 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;}}

З розривами рядків:

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 за використання Marsaglia (а точніше за не використання прямого боксу-Мюллера);)
Мартін Ендер

Хіба це не лямбда? Щось на кшталт:(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;}
Джастін

2
@Quincunx Я міг би на один байт. Але мені не подобається ховати декларації своїх функцій у незліченному коді, незалежно від поточного консенсусу щодо мета щодо цього. Варто мені одного байта;)
Геобіт

2

T-SQL, 155 байт

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

Використовуйте з EXEC RS, N, оскільки в T-SQL немає STD_IN, де S і N є насінням і N відповідно. S створить "випадкові" (RAND (насіння) дійсно погана реалізація випадкових чисел), коли S> 2 ^ 16 (можливо, до цього, але я не гарантую це). Використовує Box-Muller, як і більшість рішень досі. 8388607 є 2 ^ 23-1, що, сподіваємось, генерує 2 ^ 20 різних значень.


2

Powershell, 164 байти

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

Те саме, що більшість відповідей з Box-Muller. Не дуже досвідчений з Powershell, тому будь-яка допомога в гольфі буде вдячна.


2

Рубін, 72 байти

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

Введення (як лямбда-функція):

f.(6, 12353405)

Вихід:

-1.1565142460805273
0.9352802655317097
1.3566720571574993
-0.9683973210257978
0.9851210877202192
0.14709635752306677

PS: Я хотів би знати, чи можна далі займатися гольфом. Я просто новачок.


@ MartinBüttner Я думаю, що я використовував занадто багато C в ці дні. Повністю забув.
Zero Fiber

2

Матлаб, 77

Перший вхід повинен бути n, другий s.

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

2

Октава, 91 96 88 байт

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

Або з пробілом:

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

Встановіть насіння спереду та використовуйте метод Box-Mueller.

Примітка: Octave дозволяє генерувати масиви випадкових чисел і може використовувати стандартні операції над цими масивами, які створюють виходи масивів. .*Оператор є елемент-на-елементом множення двох масивів для отримання результату.


Я думаю, що це не відповідає умовам, якщо ви телефонуєте n(0,1)і n(0,2)отримуєте різні перші номери, чи не так?
недолік

Лайно, ти прав. Я це виправив, але це коштувало мені 5 байт ...
dcsohl

2

Pyth, 32 байти

Жоден Python не використовується зараз у суперцитатах через нові функції Pyth. Ще одна коробка-Мюллер.

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

Цей простір на початку важливий.

.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

Насіння, здається, не працює в онлайн-перекладачі, але він працює чудово в локальній версії. Інтернет-перекладач начебто виправлений, тому ось постійна посилання: постійна посилання


1
При використанні питання використовується функція Pyth ( .nZ), яка не була реалізована. (Він був реалізований сьогодні.) Тому ця відповідь не повинна бути частиною конкуренції ( meta.codegolf.stackexchange.com/questions/4867/… ).
Якубе

К, я повернусь до рішення 32-ти
чарівників

Так, було б краще. Ви все ще можете показати вам нове рішення в окремому розділі відповіді. Але кодом, який змагається, повинен бути той, який працює зі старим Pyth.
Якубе

1
До речі, я також не вважаю, що рішення 32 має бути дійсним. Оскільки він використовує випадкове насінне ініціалізоване, яке було додано лише близько 5 днів тому.
Якубе

1

STATA, 85 байт

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

Вводиться за допомогою стандартного в (спочатку число S, потім N). Встановлює насіння на S. Встановлює кількість спостережень у N. Зміна змінної та встановлює її значення на значення трансформації Box Muller (завдяки @Alex, що показав це). Потім перелічує всі спостереження в таблиці із заголовком стовпця a та номерами спостереження поруч. Якщо це не в порядку, повідомте мене, і я можу видалити заголовки та / або номери спостереження.


1

R, 89 байт

Я знаю, що R було зроблено раніше, але я хотів показати інший підхід, ніж Box-Muller, який використовували всі інші. У моєму рішенні використовується теорема центральної межі .

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

1
Боюся, теорема центрального граничного рівня не задовольняє "вибраний алгоритм повинен дати теоретично точний нормальний розподіл". Незалежно від того, скільки уніфікованих змінних ви додаєте, доки сума кінцева, нормальний розподіл завжди буде приблизним. (Хоча теорема про центральний межа - це хороша ідея, я повинен був виключити її саме тому, що незрозуміло, яке значення слід використовувати aу вашому коді, щоб результат був "справедливим".)
Мартін Ендер,

1
Варто було зняти;)
Міхал

1

TI-Basic, 74 байти

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

¹Фактично зворотний оператор.


1

Perl, 150 108 107 байт

Для цього використовується полярний метод Марсагліа . Називається f (S, N).

Перенесено завдання $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]}

Видалено запасні номери та визначення $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

Свіфт, 144 142

Нічого розумного, просто бачити, як працює Свіфт.

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

Я сподівався, що я можу використовувати (0 ... n) .map {}, але компілятор, схоже, не розпізнає карту {}, якщо ви не використовуєте параметр.


звичайно...? цеforEach якщо ви не хочете повернути значення, і я впевнений, що _ inобов'язковий
лише для ASCII

що /0xffffffffдля btw
лише



0

SmileBASIC, 81 байт

Що ж, тепер, коли я відповів на перше запитання, я повинен зробити все інше ...

Генерація випадкових чисел дешево, але висів ГСЧА використовує довгу функцію вбудованої в мові RANDOMIZE.

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

Можливо, є якийсь спосіб оптимізувати формулу. Я не бачу, як потрібно використовувати два дзвінки RNG.


Це буде необхідно мати два незалежних вибірок для перетворення Боксу-Мюллера
ASCII-тільки
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.