Случайный Гольф Дня № 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 различных значений для любого заданного вами номера.

  • Если имеющийся у вас однородный ГСЧ имеет меньший диапазон, не пригоден для посева или поддерживает слишком мало семян, вы должны сначала создать однородный ГСЧ с достаточно большим диапазоном поверх встроенного, либо вы должны реализовать свой собственный подходящий ГСЧ, используя семя. Эта страница может быть полезна для этого.
  • Если вы не реализуете установленный алгоритм генерации нормальных распределений, пожалуйста, включите подтверждение правильности. В любом случае выбранный вами алгоритм должен давать теоретически точное нормальное распределение (за исключением ограничений базовых типов данных PRNG или ограниченной точности).
  • Ваша реализация должна использовать и возвращать либо числа с плавающей запятой (шириной не менее 32 бит), либо числа с фиксированной запятой (шириной не менее 24 бит), и все арифметические операции должны использовать полную ширину выбранного типа.
  • Вы не должны использовать какие-либо встроенные функции, непосредственно связанные с нормальным распределением или гауссовыми интегралами, такие как функция Error или ее обратное.

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

Sи Nбудут неотрицательными целыми числами, каждое меньше 2 20 . Вывод может быть в любом удобном, однозначном списке или строковом формате.

Это код гольф, поэтому выигрывает самое короткое представление (в байтах). И, конечно же, самая короткая заявка для каждого пользователя также войдет в общую таблицу лидеров серии.

Leaderboard

Первый пост серии генерирует таблицу лидеров.

Чтобы убедиться, что ваши ответы отображаются, начните каждый ответ с заголовка, используя следующий шаблон уценки:

# Language Name, N bytes

где Nразмер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:

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

(Язык в настоящее время не отображается, но фрагмент требует и анализирует его, и я могу добавить таблицу лидеров по языкам в будущем.)


Подождите, мы можем использовать RNG не целочисленного диапазона?
Мниип

PS 2 существующих ответа, кажется, используют [0, 1) RNG с плавающей запятой, это разрешено?
Мниип

@mniip Да, RNG с плавающей точкой разрешены, при условии, что они единообразны, посеянны и способны возвращать требуемое количество различных операций с плавающей запятой.
Мартин Эндер

Ответы:


8

Dyalog 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), первые минимальные (N1, N2) записи двух выходов должны быть идентичны».
Marinus

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

Вам, вероятно, на самом деле не нужно +1, все, что он говорит, это то, что вам нужно поддерживать как минимум 2 ^ 16 различных значений. Так что работать правильно в диапазоне [1..2 ^ 16] должно быть в порядке.
марин

S = 0 сделает вычисления не повторяемыми, что нарушает указанное вами правило.
августа

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, содержащий вычисленные стандартные отклонения нормалей.

При этом используется метод Бокса-Мюллера: для двух независимых однородных случайных величин U и V, введите описание изображения здесь


Если это правильный синтаксис в R, вы можете f=не указывать (функция не обязательно должна называться, если на вашем языке нет названных функций).
Мартин Эндер

@ MartinBüttner: я ценю это предложение, но, насколько мне известно, R не знает, что делать с неназванной функцией.
Алекс А.

Я всегда получаю сообщение об ошибке, Error: unexpected '}' in "f=fu...кроме того, вы уверены, что получаете те же первые номера, если вы звоните f(0,1)и f(0,2)?
flawr

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

Это реализация преобразования Бокса-Мюллера, использующая встроенный случайный оператор Dyalog APL ?, который по умолчанию представляет собой твистер Мерсенна, который возвращает 64-битные значения, которых должно быть достаточно.

Объяснение:

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

1
В версии 14.0 ?0возвращается число с плавающей точкой от 0 до 1.
ngn

3

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

Это требует ввода через функцию и вывода через стандартный вывод. Он использует метод Бокса-Мюллера.


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

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 содержит некоторые символы, отсутствующие в Юникоде, я сделал замены: /= SHIFT+N, = SHIFT+O, = SHIFT+Q, = SHIFT+I, =SHIFT+E

Это реализует стандартное преобразование Бокса-Мюллера для генерации чисел; Я выбрал половину преобразования sin (x), потому что Commodore 64 Basic имеет двухсимвольный ярлык для sin(), но не для cos().

Хотя в руководстве указано иное, значение аргумента для RND имеет значение: если передается отрицательное число, генератор случайных чисел не просто повторно засеивается, он снова засевается этим числом . Это значительно упрощает заполнение: вместо того, чтобы использовать POKEпять ячеек памяти, мне просто нужно сделать бесполезный вызов RND, который сокращает код с двух строк / 121 байта до 1 строки / 76 байтов.

Редактировать: отыграть шесть байтов, поняв, что я могу объединить два INPUTутверждения, и что пробел после TOбыл необязательным.

Редактировать: Гольф еще семь раз: Commodore Basic, фактически, имеет Pi как встроенную константу, и его даже можно печатать на современной клавиатуре ( SHIFT+PgDnна случай, если вам интересно).


3

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

Hexdump кода:

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

Код с плавающей точкой реализует преобразование Бокса-Мюллера .


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). С тех пор это просто формула Бокса-Мюллера с некоторой бессмысленной магией для генерации списка.


2

Golflua, 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( )в 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

Многие символы были сохранены путем установки среды функции M(иначе math).


2

САС, 108

Я уже опубликовал ответ в R, который короче этого, но на PPCG очень мало ответов SAS, так почему бы не добавить еще один?

%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 не дает много подробностей о реализации ГСЧ, за исключением того, что имеет период 2 ^ 31-2.

В макросах SAS на макропеременные ссылаются с предшествующим &и разрешают их значения во время выполнения.

Как вы, вероятно, засвидетельствовали, SAS редко является реальным соперником в соревнованиях по .


2

Ява, 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 (или, скорее, за то, что не использовал прямой Box-Muller);)
Martin Ender

Разве это не лямбда? Что-то вроде:(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 Я мог бы, для одного байта. Но я не люблю прятать мои объявления функций в неисчисляемом коде, каким бы ни был текущий консенсус в отношении мета об этом. Это стоит одного байта для меня;)
Geobits

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 (seed) - очень плохая реализация случайных чисел) последовательности, когда 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 в эти дни. Полностью забыл про.
Ноль волокна

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

Установите семена впереди и используйте метод Бокса-Мюллера.

NB. Octave позволяет генерировать массивы случайных чисел и может использовать стандартные операции над этими массивами, которые создают выходные данные массива. .*Оператор является элемент-на-элементом умножение двух массивов для получения результата.


Я думаю, что это не соответствует условиям, если вы звоните n(0,1)и n(0,2)получаете разные первые номера, не так ли?
flawr

Дерьмо, вы правы. Я исправил это, но это стоило мне 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. Создает переменную и устанавливает ее значение в качестве значения преобразования Бокса-Мюллера (спасибо @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

Ничего умного, просто видя, как работает 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))}}

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


конечно...? этоforEach если вам не нужно возвращаемое значение, и я уверен, что _ inэто обязательно
только ASCII

что /0xffffffffдля btw
ASCII-только

1

Haskell , 97 байт

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

Попробуйте онлайн!

Просто ваше основное преобразование Бокса-Мюллера в бесконечном списке случайных чисел.



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.