ก่อนอื่นการนำเสนอที่คุณเชื่อมโยงจะพูดถึงตัวเลขสุ่มเพื่อความปลอดภัยเท่านั้น ดังนั้นจึงไม่อ้างว่าRandom
ไม่ดีสำหรับวัตถุประสงค์ด้านความปลอดภัย
แต่ฉันอ้างว่ามันเป็น การใช้งาน. net 4 Random
มีข้อบกพร่องหลายประการ ฉันขอแนะนำให้ใช้เฉพาะในกรณีที่คุณไม่สนใจคุณภาพของตัวเลขสุ่มของคุณ ฉันขอแนะนำให้ใช้การใช้งานของบุคคลที่สามที่ดีกว่า
ข้อบกพร่อง 1: การเพาะเมล็ด
ตัวสร้างเริ่มต้นเริ่มต้นด้วยเวลาปัจจุบัน ดังนั้นอินสแตนซ์ทั้งหมดที่Random
สร้างด้วยตัวสร้างเริ่มต้นภายในกรอบเวลาสั้น ๆ (ประมาณ 10ms) จะส่งคืนลำดับเดียวกัน เอกสารนี้จัดทำเป็นเอกสารและ "ตามการออกแบบ" นี่เป็นเรื่องที่น่ารำคาญอย่างยิ่งหากคุณต้องการใช้หลายเธรดโค้ดของคุณเนื่องจากคุณไม่สามารถสร้างอินสแตนซ์ของRandom
การทำงานของเธรดแต่ละชุดได้
วิธีแก้ปัญหาคือต้องระมัดระวังเป็นพิเศษเมื่อใช้ตัวสร้างเริ่มต้นและเริ่มต้นด้วยตนเองเมื่อจำเป็น
ปัญหาอีกประการหนึ่งคือเนื้อที่เมล็ดค่อนข้างเล็ก (31 บิต) ดังนั้นหากคุณสร้างอินสแตนซ์ 50k Random
ด้วยเมล็ดสุ่มที่สมบูรณ์แบบคุณอาจจะได้รับหมายเลขสุ่มหนึ่งลำดับสองครั้ง (เนื่องจากความขัดแย้งของวันเกิด ) ดังนั้นการเพาะเมล็ดด้วยตนเองจึงไม่ใช่เรื่องง่ายเช่นกัน
ข้อบกพร่อง 2: การแจกแจงของตัวเลขสุ่มที่ส่งคืนโดยNext(int maxValue)
มีความเอนเอียง
มีพารามิเตอร์ที่Next(int maxValue)
ไม่สม่ำเสมออย่างชัดเจน ตัวอย่างเช่นถ้าคุณคำนวณr.Next(1431655765) % 2
คุณจะได้0
ตัวอย่างประมาณ 2/3 ของตัวอย่าง (โค้ดตัวอย่างท้ายคำตอบ)
ข้อบกพร่อง 3: NextBytes()
วิธีนี้ไม่มีประสิทธิภาพ
ต้นทุนต่อไบต์ของ NextBytes()
Next()
เป็นเรื่องที่ใหญ่เป็นค่าใช้จ่ายในการสร้างตัวอย่างเต็มรูปแบบกับจำนวนเต็ม จากนี้ฉันสงสัยว่าพวกเขาสร้างหนึ่งตัวอย่างต่อไบต์
การนำไปใช้งานที่ดีขึ้นโดยใช้ 3 ไบต์จากแต่ละตัวอย่างจะเร็วNextBytes()
ขึ้นเกือบเป็นปัจจัย 3
ขอบคุณข้อบกพร่องนี้ Random.NextBytes()
นี้เร็วกว่าSystem.Security.Cryptography.RNGCryptoServiceProvider.GetBytes
เครื่องของฉันประมาณ 25% (Win7, Core i3 2600MHz)
ฉันแน่ใจว่ามีใครตรวจสอบรหัสไบต์ต้นทาง / ถอดรหัสแล้วพวกเขาจะพบข้อบกพร่องมากกว่าที่ฉันพบจากการวิเคราะห์กล่องดำของฉัน
ตัวอย่างโค้ด
r.Next(0x55555555) % 2
มีความลำเอียงอย่างมาก:
Random r = new Random();
const int mod = 2;
int[] hist = new int[mod];
for(int i = 0; i < 10000000; i++)
{
int num = r.Next(0x55555555);
int num2 = num % 2;
hist[num2]++;
}
for(int i=0;i<mod;i++)
Console.WriteLine(hist[i]);
ประสิทธิภาพ:
byte[] bytes=new byte[8*1024];
var cr=new System.Security.Cryptography.RNGCryptoServiceProvider();
Random r=new Random();
for(int i=0;i<100000;i++)
{
r.NextBytes(bytes);
}
for(int i=0;i<100000;i++)
{
for(int j=0;j<bytes.Length;j++)
bytes[j]=(byte)r.Next();
}
for(int i=0;i<100000;i++)
{
for(int j=0;j+2<bytes.Length;j+=3)
{
int num=r.Next();
bytes[j+2]=(byte)(num>>16);
bytes[j+1]=(byte)(num>>8);
bytes[j]=(byte)num;
}
}
for(int i=0;i<100000;i++)
{
cr.GetBytes(bytes);
}