สร้างการสุ่มลอยระหว่าง 0 ถึง 1


84

ฉันพยายามสร้างตัวเลขสุ่มที่อยู่ระหว่าง 0 ถึง 1 ฉันอ่านarc4random()มาเรื่อย ๆ แต่ไม่มีข้อมูลใด ๆ เกี่ยวกับการลอยจากมัน ฉันต้องทำอย่างไร


1
ไม่ซ้ำกันดูเหมือนจะเป็นคำถามเดียวที่เกี่ยวข้องกับการลอยตัวอย่างชัดเจน
P i

คำตอบ:


139

ค่าสุ่มใน[0, 1 [ (รวม 0, ไม่รวม 1):

บิตรายละเอียดเพิ่มเติมที่นี่

ช่วงจริงคือ[0, 0.999999999767169356]เนื่องจากขอบเขตบนคือ (คู่) 0xFFFFFFFF / 0x100000000


ขอขอบคุณ. คำตอบที่ตรงไปตรงมาที่สุดที่ฉันเคยเห็น ฉันจะอ่านลิงค์ของคุณและรับรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ ขอบคุณอีกครั้ง.
jini

3
มันแปลกที่ARC4RANDOM_MAXจะต้องมีการกำหนดด้วยตนเอง แต่0x100000000เป็น 4294967296ULONG_MAX + 1ซึ่งเป็น มีการบันทึกไว้ที่ใดว่าarc4random()ค่าสูงสุดเป็นULONG_MAXอย่างไร
bobobobo

@bobobobo จากที่นี่: developer.apple.com/library/mac/#documentation/Darwin/Reference/…ฟังก์ชัน arc4random () จะส่งกลับตัวเลขสุ่มหลอกในช่วง 0 ถึง (2 ** 32) -1
Vladimir

8
จริงๆแล้วค่าควรเป็น 0xFFFFFFFF, (2 ** 32) -1 == 0x100000000 - 0x1 == 0xFFFFFFFF == UINT32_MAX ตามที่JörgBühmannระบุไว้ในลิงก์
Josejulio

1
ค่าที่สร้างด้วยวิธีนี้ไม่รับประกันว่าจะกระจายอย่างสม่ำเสมอ!
kelin

107

ฟังก์ชัน drand48 () และ erand48 () จะส่งคืนค่าที่ไม่เป็นลบความแม่นยำสองเท่าค่าทศนิยมกระจายสม่ำเสมอในช่วงเวลา [0.0, 1.0]


19
นี่น่าจะเป็นคำตอบที่ดีที่สุด
John Riselvato

คุณอาจต้องอัปเดตคำตอบเพียงเล็กน้อยฉันอ่านใน NSHipsterที่drand48ต้องเริ่มต้นครั้งเดียวด้วยเมล็ดพันธุ์ เอกสารแอปเปิ้ลยังแนะนำว่าควรจะเริ่มต้น
dulaccc

1
เมล็ดพันธุ์เป็นสิ่งจำเป็นเนื่องจากทำให้เครื่องกำเนิดไฟฟ้าแบบสุ่มนี้เป็นจุดเริ่มต้นสำหรับการคำนวณ หากไม่มีลำดับแบบสุ่มจะเหมือนกันเสมอในการเปิดตัวแอป
Jovan Stankovic

นี่คือคำตอบที่ดีที่สุด
sabiland

คำตอบนี้ไม่ใช่คำตอบที่แม่นยำที่สุดสำหรับไฟล์double. ดูstackoverflow.com/a/34765674/1033581เกี่ยวกับวิธีการบรรลุความแม่นยำที่ดีที่สุด
Cœur

16

สำหรับ Swift 4.2+ ดู: https://stackoverflow.com/a/50733095/1033581


ด้านล่างนี้เป็นคำแนะนำสำหรับความสม่ำเสมอที่ถูกต้องและความแม่นยำที่เหมาะสมที่สุดสำหรับ ObjC และ Swift 4.1

ความแม่นยำ 32 บิต (เหมาะสมที่สุดสำหรับFloat)

ค่าสุ่มสม่ำเสมอใน[0, 1] (รวม 0.0 และ 1.0) ความแม่นยำสูงสุด 32 บิต:

Obj-C :

รวดเร็ว :

เหมาะสำหรับ:

  • a Float(หรือFloat32) ซึ่งมีนัยสำคัญและความแม่นยำ 24 บิตสำหรับแมนทิสซา

ความแม่นยำ 48 บิต (ท้อแท้)

ง่ายต่อการบรรลุความแม่นยำ 48 บิตด้วยdrand48( ซึ่งใช้arc4random_bufใต้ฝากระโปรง ) แต่โปรดทราบว่าdrand48 มีข้อบกพร่องเนื่องจากความต้องการเมล็ดพันธุ์และยังเป็นจุดต่ำสุดในการสุ่ม Double mantissa ทั้งหมด 52 บิต

ค่าสุ่มสม่ำเสมอใน[0, 1] , ความแม่นยำ 48 บิต:

รวดเร็ว :

ความแม่นยำ 64 บิต (เหมาะสมที่สุดสำหรับDoubleและFloat80)

ค่าสุ่มสม่ำเสมอใน[0, 1] (รวม 0.0 และ 1.0) ความแม่นยำสูงสุด 64 บิต:

รวดเร็วโดยใช้สองการโทรไปที่ arc4random:

รวดเร็วโดยใช้การเรียกหนึ่งครั้งเพื่อ arc4random_buf:

เหมาะสำหรับ:

  • a Double(หรือFloat64) ซึ่งมีความสำคัญและความแม่นยำ 52 บิตสำหรับแมนทิสซา
  • Float80ซึ่งมีความแม่นยำซิก 64 บิตสำหรับ mantissa ของมัน

หมายเหตุ

เปรียบเทียบกับวิธีการอื่น ๆ

คำตอบในกรณีที่ช่วงไม่รวมหนึ่งในขอบเขต (0 หรือ 1) มีแนวโน้มว่าจะได้รับความเอนเอียงที่สม่ำเสมอและควรหลีกเลี่ยง

  • โดยใช้arc4random()ความแม่นยำที่ดีที่สุดคือ 1 / 0xFFFFFFFF (UINT32_MAX)
  • โดยใช้arc4random_uniform()ความแม่นยำที่ดีที่สุดคือ 1 / 0xFFFFFFFE (UINT32_MAX-1)
  • โดยใช้rand()( แอบใช้ arc4random ) ความแม่นยำที่ดีที่สุดคือ 1 / 0x7FFFFFFF (RAND_MAX)
  • โดยใช้random()( แอบใช้ arc4random ) ความแม่นยำที่ดีที่สุดคือ 1 / 0x7FFFFFFF (RAND_MAX)

มันเป็นไปไม่ได้ในทางคณิตศาสตร์เพื่อให้บรรลุดีกว่า 32 บิตความแม่นยำกับสายเดียวarc4random, arc4random_uniform, หรือrand randomดังนั้นโซลูชัน 32 บิตและ 64 บิตข้างต้นของเราควรจะดีที่สุดที่เราสามารถทำได้


'Float80' ไม่พร้อมใช้งานบนอุปกรณ์ iOS จริง (ใช้ได้กับโปรแกรมจำลองเท่านั้น)
Cœur

10

ฟังก์ชันนี้ใช้ได้กับช่วงลูกลอยเชิงลบเช่นกัน:


4
การทำงานของโมดูลัสภายนอก ใช้Min+(Max-Min)*((float)arc4random())/ULONG_MAXแทน (float)หล่อเป็นเพียงความหวาดระแวง
bobobobo

@bobobobo ในขณะที่ฉันเห็นด้วยกับโมดูลัสภายนอกฉันแนะนำให้หารด้วย UINT32_MAX (4294967295 เสมอ) แทน ULONG_MAX (18446744073709551615 บน 64 บิต)
Cœur

7

Swift 4.2+

Swift 4.2 เพิ่มการรองรับเนทีฟสำหรับค่าสุ่มในช่วง:

เอกสาร:


1

โพสต์ก่อนหน้านี้ระบุ "rand ()" เพียงอย่างเดียวไม่ถูกต้อง นี่เป็นวิธีที่ถูกต้องในการใช้ Rand ()

สิ่งนี้จะสร้างตัวเลขระหว่าง 0 -> 1

เอกสาร BSD:

ฟังก์ชัน Rand () จะคำนวณลำดับของจำนวนเต็มสุ่มหลอกใน
ช่วง 0 ถึง RAND_MAX (ตามที่กำหนดโดยไฟล์ส่วนหัว "stdlib.h")


1

นี่คือส่วนขยายสำหรับ Float สุ่มหมายเลขSwift 3.1


@ Cœurขอบคุณที่ฉันเปลี่ยน
YannSteph

1

สวิฟต์ 4.2

Swift 4.2 ได้รวม API ตัวเลขสุ่มแบบเนทีฟและค่อนข้างสมบูรณ์ในไลบรารีมาตรฐาน ( ข้อเสนอ Swift Evolution SE-0202 )

ประเภทตัวเลขทั้งหมดมีฟังก์ชันสุ่มคงที่(ใน :)ซึ่งรับช่วงและส่งกลับตัวเลขสุ่มในช่วงที่กำหนด


0

ใช้สิ่งนี้เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับขอบเขตบนของarc4random ()

โปรดทราบว่าใช้ได้กับ MAC_10_7, IPHONE_4_3 และสูงกว่า


มีปัญหาพื้นฐานเกี่ยวกับเรื่องนี้ สังเกตได้ง่ายเมื่อคุณตั้งค่า upper_bound เป็น 10, arc4random_uniform จะคืนค่าจาก 0 ถึง 9 และผลลัพธ์สุดท้ายจะอยู่ที่ 0.0000 ถึง 0.9000 upper_bound-1คุณควรหารด้วย อย่างไรก็ตามคุณยังคงมีความแม่นยำต่ำตามอำเภอใจซึ่งเกิดจาก upper_bound ดังนั้นคุณควรเพิ่ม upper_bound เป็น UINT32_MAX และคุณจะได้รับความแม่นยำที่ดียิ่งขึ้นจากการใช้แทนarc4random()*1.0 / UINT32_MAX arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
Cœur

-1

arc4random มีช่วงได้ถึง 0x100000000 (4294967296)

นี่เป็นอีกทางเลือกหนึ่งที่ดีในการสร้างตัวเลขสุ่มระหว่าง 0 ถึง 1:


arc4random ค่าสูงสุดคือ 0xFFFFFFFF
Cœur

ขอบคุณ @ Cœur ..max val 0xFFFFFFFF ฉันไม่รู้
Gurunatha Dogi

โซลูชันของคุณก็เหมือนกับคำตอบของ Jovan Stankovic
Cœur

โอ้ฉันไม่เห็นแบบนั้น @ Cœur
Gurunatha Dogi

-4

ที่สร้างการลอยแบบสุ่ม bewteen 0 และ 1 ข้อมูลเพิ่มเติมที่นี่


3
หมายเหตุ: ให้เฉพาะ 11 ค่าที่ไม่ต่อเนื่อง: 0.0, 0.1, 0.2, ... , 1.0
TalkLittle

8
ใช่การดำเนินการของโมดูลัสจะตัดผลลัพธ์ของ arc4random () ให้อยู่ระหว่าง 0 ถึง 10 จากนั้นจึงหารด้วย 10 คำตอบนี้ไม่ดีสำหรับการใช้งานทั่วไป
bobobobo

-4

โดยค่าเริ่มต้นจะสร้างตัวเลขสุ่ม (ลอย) ระหว่าง 0 ถึง 1


4
สิ่งนี้สร้าง int แบบสุ่มสำหรับฉัน
AlexQueue

rand()ไม่ได้ดูเหมือนจะมีอยู่บน iOSและถ้ามันไม่ได้ก็จะผลิตเป็นจำนวนเต็มเช่นมันไม่เกี่ยวกับทุก NIX * อื่น ๆ
jscs

2
@JoshCaswell rand()เป็นส่วนหนึ่งของ C ซึ่งเป็นส่วนหนึ่งของ Objective-C (ซึ่งใช้ในการเขียนโปรแกรม iOS) ฟังก์ชั่น C เหมือนrand()มีอยู่จริงบน iOS แต่arc4random()เป็นที่ต้องการ
Frungi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.