สุ่มกอล์ฟประจำวัน # 2: ตัวเลขจากการแจกแจงแบบปกติ


12

เกี่ยวกับซีรี่ส์

ก่อนอื่นคุณอาจปฏิบัติเช่นนี้กับการแข่งขันกอล์ฟอื่น ๆ และตอบคำถามโดยไม่ต้องกังวลเกี่ยวกับซีรี่ส์เลย อย่างไรก็ตามมีลีดเดอร์บอร์ดสำหรับทุกความท้าทาย คุณสามารถค้นหาลีดเดอร์พร้อมกับข้อมูลบางอย่างเพิ่มเติมเกี่ยวกับซีรีส์ในโพสต์แรก

แม้ว่าฉันจะมีแนวความคิดมากมายสำหรับซีรีส์ แต่ความท้าทายในอนาคตยังไม่เกิดขึ้น หากคุณมีข้อเสนอแนะใด ๆ โปรดแจ้งให้เราทราบเกี่ยวกับการโพสต์ Sandbox ที่เกี่ยวข้อง

หลุม 2: ตัวเลขจากการแจกแจงแบบปกติ

ฉันไม่อยากจะเชื่อเลยว่านี่ยังไม่ได้ทำ! คุณจะสร้างตัวเลขสุ่ม, การวาดภาพจากการแจกแจงแบบปกติ กฎบางอย่าง (ส่วนใหญ่ของพวกเขาอาจถูกครอบคลุมโดยอัตโนมัติโดยการส่งส่วนใหญ่ แต่บางคนอยู่ในสถานที่เพื่อให้แน่ใจว่าผลลัพธ์ที่สอดคล้องกันระหว่างภาษาที่แตกต่างกันอย่างมากมาย):

  • คุณควรใช้จำนวนเต็มที่ไม่เป็นลบสองตัวเป็นอินพุต : seed SและจำนวนNของตัวเลขที่จะส่งคืน การส่งออกควรจะมีรายการของNหมายเลขจุดลอยมาจากการแจกแจงแบบปกติที่มีค่าเฉลี่ย 0และความแปรปรวน 1 เมื่อใดก็ตามที่การส่งของคุณได้รับเมล็ดเดียวกันSก็ควรสร้างหมายเลขเดียวกัน โดยเฉพาะอย่างยิ่งถ้ามันถูกเรียกครั้งเดียวและครั้งเดียวกับรายการแรกของทั้งสองเอาท์พุทควรจะเหมือนกัน นอกจากนี้อย่างน้อย 2 16ค่าที่ต่างกันควรสร้างลำดับที่แตกต่างกัน(S, N1)(S, N2)min(N1, N2)S

  • คุณสามารถใช้เครื่องกำเนิดตัวเลขสุ่มแบบบิวท์อินใด ๆ ที่มีเอกสารเพื่อดึงตัวเลขจากการแจกแจงแบบสม่ำเสมอ (โดยประมาณ) หากคุณสามารถส่งSต่อไปได้และสนับสนุนอย่างน้อย 2 16เมล็ดที่แตกต่างกัน หากคุณทำเช่นนั้นRNG ควรจะสามารถส่งคืนค่าที่แตกต่างกันอย่างน้อย 2 20ค่าสำหรับหมายเลขใดก็ตามที่คุณร้องขอจากมัน

  • หาก RNG เครื่องแบบที่มีของคุณมีช่วงที่มีขนาดเล็กไม่ seedable หรือสนับสนุนน้อยเกินไปเมล็ดคุณต้องแรกสร้าง RNG เครื่องแบบมีช่วงขนาดใหญ่พอที่ด้านบนของตัวเครื่องในหนึ่งหรือคุณต้องใช้ของคุณเองRNG เหมาะใช้ เมล็ด. หน้านี้อาจมีประโยชน์สำหรับสิ่งนั้น
  • หากคุณไม่ได้ใช้อัลกอริทึมที่กำหนดไว้สำหรับการสร้างการแจกแจงแบบปกติโปรดระบุหลักฐานความถูกต้อง ไม่ว่าในกรณีใดอัลกอริทึมที่คุณเลือกจะต้องให้การแจกแจงปกติที่แน่นอนตามหลักทฤษฏี (ยกเว้นข้อ จำกัด ของชนิดข้อมูล PRNG หรือความแม่นยำที่ จำกัด )
  • การใช้งานของคุณควรใช้และส่งกลับจำนวนจุดลอยตัว (อย่างน้อย 32 บิตกว้าง)หรือหมายเลขจุดคงที่ (อย่างน้อย 24 บิตกว้าง)และการดำเนินการทางคณิตศาสตร์ทั้งหมดควรใช้ความกว้างเต็มของประเภทที่เลือก
  • คุณต้องไม่ใช้ฟังก์ชันในตัวที่เกี่ยวข้องโดยตรงกับการแจกแจงแบบปกติหรืออินทิกรัลเกาส์เช่นฟังก์ชันข้อผิดพลาดหรือผกผัน

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่นเต็มรูปแบบและรับอินพุตผ่าน STDIN อาร์กิวเมนต์บรรทัดคำสั่งอาร์กิวเมนต์ฟังก์ชันหรือพร้อมท์และสร้างเอาต์พุตผ่านค่าส่งคืนหรือโดยการพิมพ์ไปยัง STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด)

SและNจะไม่ integers ลบแต่ละน้อยกว่า 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 เนื่องจากมีความสม่ำเสมอสม่ำเสมอสามารถเพาะได้และสามารถคืนจำนวนลอยที่ต้องการได้
Martin Ender

คำตอบ:


8

Dyalog APL 33 ไบต์

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

กล่องมุลเลอร์ :

⎕         ⍝ 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)

ฉันค่อนข้างมั่นใจว่าภาษานี้ไม่สามารถเอาชนะได้ด้วยภาษาอื่น
Zero Fiber

2
สิ่งนี้ไม่เป็นไปตามกฎนี้: "โดยเฉพาะถ้ามันถูกเรียกครั้งเดียวด้วย (S, N1) และอีกครั้งด้วย (S, N2) รายการ min (N1, N2) แรกของสองเอาต์พุตควรเหมือนกัน"
marinus

@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()ซึ่งโดยค่าเริ่มต้นใช้อัลกอริทึม Mersenne-Twister ที่มีระยะเวลา 2 ^ 19937-1

ผลลัพธ์คือเวกเตอร์ R ของความยาว N ที่มีค่าเบี่ยงเบนมาตรฐานที่คำนวณได้

สิ่งนี้ใช้วิธี Box-Muller: สำหรับตัวแปรสุ่มที่เหมือนกันสองตัว U และ V ป้อนคำอธิบายรูปภาพที่นี่


หากนั่นคือไวยากรณ์ที่ถูกต้องใน R คุณสามารถละทิ้งf=(ฟังก์ชันนั้นไม่จำเป็นต้องตั้งชื่อถ้าฟังก์ชันที่ไม่มีชื่อนั้นเป็นภาษาของคุณ)
Martin Ender

@ MartinBüttner: ฉันขอขอบคุณข้อเสนอแนะ แต่สำหรับความรู้ของฉัน R จะไม่ทราบว่าจะทำอย่างไรกับฟังก์ชั่นที่ไม่มีชื่อ
Alex A.

ฉันได้รับข้อความแสดงข้อผิดพลาดเสมอError: unexpected '}' in "f=fu...คุณแน่ใจหรือไม่ว่าคุณได้รับหมายเลขแรกเหมือนกันถ้าคุณโทรf(0,1)และf(0,2)?
ข้อบกพร่อง

4

Dyalog APL, 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 ?ซึ่งโดยค่าเริ่มต้นคือ Twers 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

Perl, 67

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

Box-Muller เช่นเดียวกับในรายการอื่น ๆ ใช้พารามิเตอร์ในการสั่งซื้อfS, 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;?
Geobits

1
@Geobits ดูเหมือนแลมบ์ดา: D
TheNumberOne

3

พลเรือจัตวา 64 พื้นฐาน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 มาตรฐานเพื่อสร้างตัวเลข ฉันเลือกบาป (x) ครึ่งหนึ่งของการแปลงเพราะ 64 จัตวาพื้นฐานมีทางลัดสองตัวอักษรสำหรับแต่ไม่ได้สำหรับsin()cos()

แม้ว่ารัฐคู่มือมิฉะนั้นค่าของการโต้แย้งที่จะRND ไม่ว่าถ้าจำนวนลบจะผ่านเครื่องกำเนิดไฟฟ้าจำนวนสุ่มไม่ได้เป็นเพียงอีกเมล็ดก็เป็นอีกครั้งที่เมล็ดมีตัวเลขที่ สิ่งนี้ทำให้การ seed ง่ายขึ้นมาก: แทนที่จะต้องการ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;
    }
}

นี่ผมใช้ AA เครื่องกำเนิดไฟฟ้าจำนวนสุ่ม Lehmer มันใช้อัลกอริทึมต่อไปนี้:

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

นี่ 4294967291 เป็นใหญ่ (2 ^ 32-5) จำนวนเฉพาะและ 116 มีขนาดเล็ก (น้อยกว่า 128; ดูด้านล่าง) ตัวเลขที่เป็นของรากดั้งเดิม ฉันเลือกรากดั้งเดิมที่มีการแจกแจงแบบศูนย์มากกว่าหรือน้อยกว่าในรูปแบบเลขฐานสอง (01110100) RNG นี้มีช่วงเวลาที่เป็นไปได้สูงสุดที่ 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

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

ตัวอย่างการใช้งาน:

*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(aka math)


2

SAS, 108

ฉันโพสต์คำตอบใน Rที่สั้นกว่านี้แล้ว แต่มีคำตอบ SAS น้อยมากใน 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 ไม่มีบิวท์อินสำหรับไพดังนั้นสิ่งที่ดีที่สุดที่เราทำได้คือประมาณด้วยอาร์คแทนเจนต์

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 (หรือมากกว่าสำหรับการไม่ใช้ 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;}
Justin

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 เพราะไม่มี STD_IN ใน T-SQL โดยที่ 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

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

Matlab, 77

อินพุตแรกที่ควรจะหนึ่งที่สองns

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 มีตอนนี้ อีกหนึ่ง Box-Mueller

 .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

ดูเหมือนว่าการเพาะจะไม่ทำงานในล่ามออนไลน์ แต่ก็ใช้ได้ดีในรุ่นท้องถิ่น ดูเหมือนล่ามออนไลน์จะได้รับการแก้ไขดังนั้นนี่เป็นความคิดเห็น: permalink


1
สิ่งนี้ใช้คุณสมบัติของ Pyth ( .nZ) ที่ไม่ได้ใช้งานเมื่อถามคำถาม (มันถูกนำไปใช้จริงในวันนี้) ดังนั้นคำตอบนี้ไม่ควรเป็นส่วนหนึ่งของการแข่งขัน ( meta.codegolf.stackexchange.com/questions/4867/ … )
Jakube

K ฉันจะกลับไปที่วิธีแก้ปัญหาถ่าน 32 ตัว
Maltysen

ใช่ว่าจะดีกว่า คุณยังสามารถแสดงโซลูชันใหม่ให้คุณได้ในส่วนที่แยกจากกันของคุณ แต่รหัสของการแข่งขันของคุณควรเป็นรหัสที่ทำงานกับ Pyth แบบเก่า
Jakube

1
Btw ฉันไม่คิดว่าโซลูชัน 32 ควรจะใช้ได้เช่นกัน เนื่องจากมันใช้การสุ่มเริ่มต้นเมล็ดซึ่งถูกเพิ่มเข้ามาเพียงประมาณ 5 วันที่ผ่านมา
Jakube

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 แล้ว) ตั้งค่า seed เป็น S ตั้งค่าจำนวนการสังเกตเป็น N สร้างตัวแปรและตั้งค่าเป็นค่าการแปลง Box Muller (ขอบคุณ @Alex สำหรับการแสดง) จากนั้นแสดงรายการการสังเกตทั้งหมดในตารางที่มีส่วนหัวคอลัมน์ a และหมายเลขการสังเกตถัดจากพวกเขา หากสิ่งเหล่านี้ไม่เป็นไรแจ้งให้เราทราบและฉันสามารถลบส่วนหัวและ / หรือหมายเลขการสังเกตได้


1

R, 89 Bytes

ฉันรู้ว่า 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ในโค้ดของคุณเพื่อให้ผลลัพธ์เป็น "ยุติธรรม")
Martin Ender

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 ไบต์

นี้ใช้Marsaglia วิธีขั้วโลก เรียกว่าด้วย 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 {} แต่คอมไพเลอร์ดูเหมือนจะไม่รู้จักแผนที่ {} เว้นแต่คุณจะใช้พารามิเตอร์


แน่นอน...? ก็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

ลองออนไลน์!

เพียงแค่การแปลง Box-Muller พื้นฐานของคุณในรายการตัวเลขสุ่มที่ไม่มีที่สิ้นสุด



0

SmileBASIC, 81 ไบต์

ทีนี้เมื่อฉันตอบคำถามแรกฉันต้องทำทั้งหมดที่เหลือ ...

การสร้างตัวเลขสุ่มราคาถูก แต่การเพาะ RNG จะใช้ยาวที่สุดในRANDOMIZEฟังก์ชั่นในตัวในภาษา

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

อาจมีวิธีการเพิ่มประสิทธิภาพสูตรบางอย่าง ฉันไม่เห็นวิธีการใช้ RNG สองสาย


มันจะต้องมีสองกลุ่มที่เป็นอิสระสำหรับการเปลี่ยนแปลงกล่องมุลเลอร์
ASCII เท่านั้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.