RandomKit เป็นเฟรมเวิร์กที่รวดเร็วซึ่งทำให้การสร้างข้อมูลแบบสุ่มง่ายและง่าย
| สาขา | สถานะ |
|---|---|
master |
RandomKit อาจเข้ากันได้กับ FreeBSD, Android และ Windows (ภายใต้ Cygwin) แต่ยังไม่ได้รับการทดสอบสำหรับแพลตฟอร์มเหล่านั้น
Swift Package Manager เป็นตัวจัดการการพึ่งพากระจายอำนาจสำหรับ Swift
เพิ่มโครงการลงใน Package.swift ของคุณ
import PackageDescription
let package = Package (
name : " MyAwesomeProject " ,
dependencies : [
. Package ( url : " https://github.com/nvzqz/RandomKit.git " ,
majorVersion : 5 )
]
)นำเข้าโมดูล RandomKit
import RandomKitCocoapods เป็นตัวจัดการการพึ่งพาส่วนกลางสำหรับ Objective-C และ Swift ไปที่นี่เพื่อเรียนรู้เพิ่มเติม
เพิ่มโครงการลงใน PodFile ของคุณ
use_frameworks!
pod 'RandomKit' , '~> 5.2.3'หากคุณต้องการที่จะอยู่บนขอบเลือดให้แทนที่บรรทัดสุดท้ายด้วย:
pod 'RandomKit' , :git => 'https://github.com/nvzqz/RandomKit.git' เรียกใช้ pod install และเปิดไฟล์ .xcworkspace เพื่อเรียกใช้ XCode
นำเข้า Framework RandomKit
import RandomKitคาร์เธจเป็นตัวจัดการการพึ่งพากระจายอำนาจสำหรับ Objective-C และ Swift
เพิ่มโครงการลงใน CartFile ของคุณ
github "nvzqz/RandomKit"
เรียกใช้ carthage update และทำตามขั้นตอนเพิ่มเติมเพื่อเพิ่ม RandomKit ให้กับโครงการของคุณ
นำเข้า Framework RandomKit
import RandomKit ส่วนประกอบต่าง ๆ ของ RandomKit สามารถเปรียบเทียบได้อย่างง่ายดายโดยใช้ benchmark.sh
./benchmark.sh [FLAGS] [PROTOCOLS] ใช้ --help Flag สำหรับข้อมูลเกี่ยวกับวิธีการใช้งาน
หมายเหตุ: การนับเริ่มต้นคือ 10,000,000 ซึ่งเป็นจำนวนมากหากใช้ธง --array สิ่งนี้สามารถเปลี่ยนแปลงได้โดยส่งอาร์กิวเมนต์ไปยัง --count หรือ -c
ลองด้วยตัวคุณเอง! ดาวน์โหลด repo และเปิด 'randomkit.playground'
โปรโตคอล RandomGenerator กำหนดวิธีการพื้นฐานสำหรับการสร้างค่าดั้งเดิมและการสุ่มบัฟเฟอร์
ทุกประเภทที่ให้ไว้ซึ่งสอดคล้องกับ RandomGenerator มีค่า default คงที่ซึ่งสามารถส่งผ่านเป็นอาร์กิวเมนต์ inout ไปยังฟังก์ชั่นการสร้าง
let value = Int . random ( using : & Xoroshiro . default ) ARC4Random
arc4random ของฟังก์ชั่นไม่ได้ส่งออกด้วย Foundation on Linux และแพลตฟอร์มอื่น ๆ จึงมีการโหลดแบบไดนามิกที่รันไทม์ DeviceRandom
MersenneTwister
Xoroshiro
Xorshift
XorshiftStar
ChaCha
SeedableRandomGenerator มีไว้สำหรับประเภทที่สามารถเพาะเมล็ดด้วยชนิด Seed ที่เกี่ยวข้อง
โปรโตคอล RandomBytesGenerator มีไว้สำหรับประเภทที่เชี่ยวชาญในการสร้างประเภทเฉพาะที่เติมจำนวนไบต์ ตัวอย่างเช่น MersenneTwister เชี่ยวชาญในการสร้าง UInt64 ในขณะที่ Xorshift สร้างค่า UInt32
สำหรับโปรแกรมแบบเธรดเดี่ยวมันปลอดภัยที่จะใช้อินสแตนซ์ Global Generator เช่น Xoroshiro.default เป็นแหล่งของการสุ่ม
สำหรับโปรแกรมมัลติเธรดควรใช้อินสแตนซ์เธรดท้องถิ่น สิ่งนี้ช่วยให้เธรดที่แตกต่างกันสามารถใช้เครื่องกำเนิดไฟฟ้าแบบสุ่มแยกต่างหากโดยไม่มีสถานะที่ไม่แน่นอนที่ใช้ร่วมกัน
ในตัวอย่างต่อไปนี้ randomGenerator นั้นไม่ซ้ำกันในแต่ละเธรด
let randomBytes = Xoroshiro . withThreadLocal { randomGenerator in
return [ UInt8 ] ( randomCount : 1000 , using : & randomGenerator )
}เครื่องกำเนิดเกลียวท้องถิ่นจะถูกจัดวางเมื่อออกจากเธรดดังนั้นจึงไม่จำเป็นต้องกังวลเกี่ยวกับการทำความสะอาด
ขอแนะนำให้ไม่โทร withThreadLocal(_:) หรือรับตัวชี้ threadLocal ในแต่ละครั้งที่จำเป็น การดึงอินสแตนซ์ของเธรดท้องถิ่นนั้นไม่สามารถหลีกเลี่ยงได้
// Bad
let value = Int . random ( using : & Xoroshiro . threadLocal . pointee )
array . shuffle ( using : & Xoroshiro . threadLocal . pointee )
// Good
let threadLocal = Xoroshiro . threadLocal
let value = Int . random ( using : & threadLocal . pointee )
array . shuffle ( using : & threadLocal . pointee )
// Better
Xoroshiro . withThreadLocal { randomGenerator in
let value = Int . random ( using : & randomGenerator )
array . shuffle ( using : & randomGenerator )
}ในฐานะทางลัดคุณสามารถใช้ฟังก์ชั่นโดยตรงเป็นพารามิเตอร์
let value = Xoroshiro . withThreadLocal ( Int . random ) ก่อนที่จะมี v4.4.0 ความปลอดภัยของด้ายสามารถทำได้โดยการสร้างอินสแตนซ์แบบใหม่ของประเภทแบบ RandomGenerator ที่กำหนด ปัญหาเกี่ยวกับเรื่องนี้คือการเพาะที่ไม่จำเป็นเกิดขึ้นในแต่ละครั้ง ด้วยสิ่งนี้เครื่องกำเนิดไฟฟ้าจะถูกเพาะหนึ่งครั้งและสามารถนำกลับมาใช้ใหม่ได้ที่จุดต่อมา
ทางลัดไปยังเวอร์ชัน Reseeding ของเครื่องกำเนิดไฟฟ้ายังมีอยู่:
Xoroshiro . withThreadLocalReseeding {
...
}วิธี ใดที่ดีกว่าการเขียน:
ReseedingRandomGenerator . withThreadLocal ( createdWith : { Xoroshiro . reseeding } ) {
...
}RandomKit เป็นโปรโตคอลที่มุ่งเน้นมากซึ่งให้ความสามารถในการยืดหยุ่นและเป็นโมดูลาร์
โปรโตคอลสำหรับประเภทที่สามารถสร้างค่าสุ่มโดยใช้ RandomGenerator
โปรโตคอลสำหรับประเภทที่สามารถสร้างค่าสุ่มเลือกภายในช่วงโดยใช้ RandomGenerator
Int . random ( in : 0 ..< 0 , using : & randomGenerator ) // nil โปรโตคอลสำหรับประเภทที่สามารถสร้างค่าสุ่มภายในช่วงปิดโดยใช้ RandomGenerator
Int . random ( in : - 100 ... 100 , using : & randomGenerator ) // -79โปรโตคอลสำหรับประเภทที่สามารถสร้างค่าสุ่มจากค่าพื้นฐานไปยังค่าอื่นไม่รวม
ค่าพื้นฐานสำหรับจำนวนเต็มคือ 0 ซึ่งหมายความว่าการเรียก random(to:using:) ในค่าลบจะให้ค่าลบแบบสุ่มหรือศูนย์ในขณะที่ค่าบวกจะให้ค่าบวกแบบสุ่มหรือศูนย์
ถ้า value == randomBase value จะถูกส่งคืนสำหรับ random(to:using:)
Int . random ( to : 2 , using : & randomGenerator ) // Either 0 or 1
Int . random ( to : 0 , using : & randomGenerator ) // Always 0
Int . random ( to : 32 , using : & randomGenerator ) // 15
Int . random ( to : - 5 , using : & randomGenerator ) // -3โปรโตคอลสำหรับประเภทที่สามารถสร้างค่าสุ่มจากค่าฐานผ่านค่าอื่นรวม
กฎเดียวกันเกี่ยวกับค่าพื้นฐานของ RandomToValue นำไปใช้กับ RandomThroughValue
โปรโตคอลสำหรับประเภทที่มีอินสแตนซ์สามารถดึงองค์ประกอบแบบสุ่มได้
[ " Bob " , " Cindy " , " May " , " Charles " , " Javier " ] . random ( using : & randomGenerator ) // "Charles"
" Hello " . characters . random ( using : & randomGenerator ) // "e" บางประเภทพื้นฐานเช่น NSArray สอดคล้องกับโปรโตคอลนี้
โปรโตคอลสำหรับประเภทที่มีอินสแตนซ์สามารถมีองค์ประกอบแบบสุ่มดึงมาจากภายใน Range<Index>
[ 20 , 37 , 42 ] . random ( in : 1 ..< 3 , using : & randomGenerator ) // Either 37 or 42โปรโตคอลสำหรับประเภทที่มีองค์ประกอบสามารถสับได้
// Array
[ 1 , 2 , 3 , 4 , 5 ] . shuffled ( using : & randomGenerator ) // [3, 4, 1, 5, 2]
// Dictionary
[ " a " : 1 , " b " : 2 , " c " : 3 ] . shuffled ( using : & randomGenerator ) // ["a": 3, "b": 1, "c": 2] คู่ที่ไม่สามารถเปลี่ยนได้ shuffled(using:) คือ shuffle(using:)
เพื่อประสิทธิภาพที่ดีขึ้นในการ Array ให้พิจารณาการสับในสถานที่ด้วย shuffle(using:)
คล้ายกับ Shuffleable ยกเว้นไม่มีองค์ประกอบอยู่ในตำแหน่งเริ่มต้น
ประเภทจำนวนเต็มดั้งเดิมของ Swift ทั้งหมดสอดคล้องกับโปรโตคอล Random-
random(using:) ฟังก์ชั่นสร้างจำนวนเต็มที่มีค่าใด ๆ เป็นผลให้ค่าลบอาจส่งผลให้จำนวนเต็มที่ลงนาม
Int . random ( using : & randomGenerator ) // An Int within Int.min and Int.max
Int . random ( in : 10 ... 20 , using : & randomGenerator ) // An Int within 10 and 20 ในการสร้างจำนวนเต็มที่ลงนามในเชิงบวกให้ใช้ random(to:using:) หรือ random(through:using:)
Int . random ( to : 1000 , using : & randomGenerator ) // 731
Int . random ( through : 10 , using : & randomGenerator ) // 4จำนวนเต็มที่ลงนามสามารถสร้างได้จากทุกช่วงโดยไม่มีอันตรายจากการล้น
Int . random ( in : ( . min + 1000 ) ... ( . max - 200 ) , using : & randomGenerator ) // 5698527899712144154 สร้างค่าจุดลอยตัวแบบสุ่มจากภายในช่วงหรือ 0.0...1.0 โดยค่าเริ่มต้น
Double . random ( using : & randomGenerator ) // 0.9813615573117475
Double . random ( in : - 10 ... 10 , using : & randomGenerator ) // -4.03042337718197
Float . random ( in : - 10 ... 10 , using : & randomGenerator ) // 5.167088
Float80 . random ( in : - 10 ... 10 , using : & randomGenerator ) // -3.63204542399198874 ทุกประเภท FloatingPoint ยังสามารถปฏิบัติตาม RandomInClosedRange รวมถึงนอกกรอบ
Bool.random(using:) มีโอกาส 50/50 ที่จะเป็น true
หากคุณต้องการความน่าจะเป็นที่แตกต่างกันก็มี random(withWeight:using:) ซึ่งมีโอกาส 1 ใน weight ที่จะเป็น true
String Character และ UnicodeScalar สร้างค่าภายใน " "..."~" โดยค่าเริ่มต้น
String . random ( ofLength : 10 , using : & randomGenerator ) // "}+[=Ng>$w1"
String . random ( ofLength : 10 , in : " A " ... " z " , using : & randomGenerator ) // "poUtXJIbv["
Character . random ( using : & randomGenerator ) // "#"
Character . random ( in : " A " ... " z " , using : & randomGenerator ) // "s" สามารถสร้างอาร์เรย์ของค่าสุ่มสำหรับประเภทที่สอดคล้องกับ Random ด้วย init(randomCount:using:)
มีการเริ่มต้นที่คล้ายกันสำหรับโปรโตคอล Random- อื่น ๆ ทั้งหมด
let randoms = Array < Int > ( randomCount : 100 , using : & randomGenerator ) // [8845477344689834233, -957454203475087100, ...] สำหรับประเภทที่สอดคล้องกับ UnsafeRandom ทางเลือกที่เร็วกว่าคือ init(unsafeRandomCount:using:) การเริ่มต้นนี้เติมบัฟเฟอร์โดยตรงแทนที่จะใช้ random(using:)
let unsafeRandoms = Array < Int > ( unsafeRandomCount : 100 , using : & randomGenerator ) // [759709806207883991, 4618491969012429761, ...] เกณฑ์มาตรฐานของการสร้างอาร์เรย์ Int สุ่ม 1,000 ครั้งที่จำนวน 10,000 นับ:
| เครื่องกำเนิดไฟฟ้า | เวลา (เป็นวินาที) |
|---|---|
Xoroshiro | 0.0271 |
Xorshift | 0.0568 |
XorshiftStar | 0.0319 |
ChaCha | 0.2027 |
MersenneTwister | 0.0432 |
ARC4Random | 0.2416 |
DeviceRandom | 5.3348 |
หมายเหตุ: ผลลัพธ์อาจแตกต่างกันไปเนื่องจากปัจจัยต่าง ๆ
เกณฑ์มาตรฐานเดียวกันนี้สามารถทำงานได้ด้วย:
./benchmark.sh --all-generators --array 10000 --count 1000 Date สุ่มสามารถสร้างได้ระหว่างสอง Date หรือค่า TimeInterval
random(using:) ฟังก์ชั่นส่งคืน Date ภายใน Date.distantPast และ Date.distantFuture
Date . random ( using : & randomGenerator ) // "Aug 28, 2006, 3:38 AM"
Date . random ( in : Date . distantPast ... Date ( ) , using : & randomGenerator ) // "Feb 7, 472, 5:40 AM" ประเภท Decimal สอดคล้องกับโปรโตคอล Random- ต่างๆ
random(using:) ฟังก์ชั่นส่งคืน Decimal ระหว่าง 0 ถึง 1 โดยค่าเริ่มต้น
Decimal . random ( using : & randomGenerator ) // 0.87490000409886706715888973957833129437
Decimal . random ( in : 0.0 ... 10.0 , using : & randomGenerator ) // 6.5464639772070720738747790627821299859 สามารถสร้างหมายเลขสุ่มจากภายในจำนวนเต็มหรือสองช่วงหรือ 0...100 โดยค่าเริ่มต้น
NSNumber . random ( using : & randomGenerator ) // 79
NSNumber . random ( in : - 50 ... 100 , using : & randomGenerator ) // -27
NSNumber . random ( in : 100 ... 200 , using : & randomGenerator ) // 149.6156950363926สามารถสร้างสีแบบสุ่มได้โดยมีหรือไม่มีอัลฟ่าแบบสุ่ม
NSColor . random ( using : & randomGenerator ) // r 0.694 g 0.506 b 0.309 a 1.0
NSColor . random ( alpha : true , using : & randomGenerator ) // r 0.859 g 0.57 b 0.409 a 0.047
UIColor . random ( using : & randomGenerator ) // r 0.488 g 0.805 b 0.679 a 1.0
UIColor . random ( alpha : true , using : & randomGenerator ) // r 0.444 g 0.121 b 0.602 a 0.085 เนื่องจาก CGFloat สอดคล้องกับ FloatingPoint จึงสอดคล้องกับ RandomInClosedRange เช่นเดียวกับวิธีที่ Double และ Float ทำ
CGFloat . random ( using : & randomGenerator ) // 0.699803650379181
CGFloat . random ( in : 0 ... 100 , using : & randomGenerator ) // 43.27969591675319จุดสุ่มสามารถสร้างได้จากภายในช่วงสำหรับ x และ y
CGPoint . random ( using : & randomGenerator ) // {x 70.093 y 95.721}
CGPoint . random ( xRange : 0 ... 200 , yRange : 0 ... 10 , using : & randomGenerator ) // {x 73.795 y 0.991}ขนาดสุ่มสามารถสร้างได้จากภายในช่วงความกว้างและความสูง
CGSize . random ( using : & randomGenerator ) // {w 3.744 h 35.932}
CGSize . random ( widthRange : 0 ... 50 , heightRange : 0 ... 400 , using : & randomGenerator ) // {w 38.271 h 239.636}รูปสี่เหลี่ยมผืนผ้าแบบสุ่มสามารถสร้างได้จากภายในช่วงสำหรับ x, y, ความกว้างและความสูง
CGRect . random ( using : & randomGenerator ) // {x 3.872 y 46.15 w 8.852 h 20.201}
CGRect . random ( xRange : 0 ... 50 ,
yRange : 0 ... 100 ,
widthRange : 0 ... 25 ,
heightRange : 0 ... 10 ,
using : & randomGenerator ) // {x 13.212 y 79.147 w 20.656 h 5.663}เวกเตอร์แบบสุ่มสามารถสร้างได้จากภายในช่วงสำหรับ DX และ DY
CGVector . random ( using : & randomGenerator ) // {dx 13.992 dy 89.376}
CGVector . random ( dxRange : 0 ... 50 , dyRange : 0 ... 10 , using : & randomGenerator ) // {dx 35.224 dy 13.463}Extensions แบบสุ่มสำหรับห้องสมุด Bigint ของKárolyมีให้บริการใน Randomkitbigint
RandomKit และสินทรัพย์ของ บริษัท จะถูกปล่อยออกมาภายใต้ใบอนุญาต MIT สินทรัพย์สามารถพบได้ในสาขา assets
บางส่วนของโครงการนี้ใช้รหัสที่เขียนโดย Matt Gallagher และร่วมกับใบอนุญาต MIT ได้รับใบอนุญาตที่พบที่นี่