ฉันจะทดสอบแบบแผนได้อย่างไร


127

พิจารณาวิธีการสุ่มองค์ประกอบในอาร์เรย์ คุณจะเขียนการทดสอบหน่วยที่เรียบง่าย แต่มีประสิทธิภาพเพื่อให้แน่ใจว่าสิ่งนี้ทำงานได้อย่างไร

ฉันคิดสองแนวคิดซึ่งทั้งสองอย่างนี้มีข้อบกพร่องที่สังเกตได้:

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

พิจารณาฟังก์ชั่นที่สองซึ่งจำลองการทอยลูกเต๋าและส่งกลับตัวเลขสุ่ม คุณจะทดสอบฟังก์ชั่นนี้อย่างไร? คุณจะทดสอบฟังก์ชั่นนี้อย่างไร ...

  • ไม่ส่งคืนตัวเลขภายนอกขอบเขตที่กำหนดหรือไม่
  • ส่งคืนตัวเลขในการแจกแจงที่ถูกต้องหรือไม่ (ชุดเดียวตายปกติสำหรับลูกเต๋าจำนวนมาก)

ฉันกำลังมองหาคำตอบที่ให้ข้อมูลเชิงลึกเกี่ยวกับการทดสอบไม่เพียง แต่ตัวอย่างเหล่านี้ แต่องค์ประกอบแบบสุ่มของรหัสโดยทั่วไป การทดสอบหน่วยเป็นวิธีการแก้ปัญหาที่เหมาะสมหรือไม่ ถ้าไม่มีการทดสอบประเภทใด


เพียงเพื่อความสบายใจของทุกคนฉันไม่ได้เขียนตัวสร้างตัวเลขสุ่มของฉันเอง


35
คลัปแน่นแสดงให้เห็นหัวของมัน ผ่านในวัตถุที่สร้างตัวเลขสุ่ม จากนั้นในระหว่างการทดสอบคุณสามารถผ่านวัตถุที่สร้างชุดของตัวเลขที่ระบุซึ่งคุณรู้ว่าสำรับดูเหมือนหลังจากการสับเปลี่ยน คุณสามารถทดสอบการสุ่มของตัวสร้างตัวเลขสุ่มของคุณแยกจากกัน
Martin York

1
ฉันจะพิจารณาใช้ไลบรารีรูทีนที่มีอยู่สำหรับ shuffle (java Collections.shuffle () หรือคล้ายกัน) อย่างยิ่ง มีเรื่องเตือนให้อ่านที่developer.com/tech/article.php/616221/…เกี่ยวกับการเขียนอัลกอริทึมแบบสุ่มที่มีข้อบกพร่อง สำหรับการเขียนฟังก์ชั่น d6 () เราจะทดสอบให้มากพอที่จะมั่นใจได้ว่ามันจะไม่สร้างหมายเลขออกนอกระยะจากนั้นทำการทดสอบไคสแควร์ในการแจกแจง (ไคสแควร์ค่อนข้างจะไวต่อการสุ่มลำดับหลอก) ดูที่สัมประสิทธิ์สหสัมพันธ์

"สิ่งนี้ขึ้นอยู่กับฟังก์ชั่นการสุ่มส่งคืนค่าเดิมที่ให้เมล็ดเดียวกันเสมออย่างไรก็ตามบางครั้งนี่อาจเป็นข้อสันนิษฐานที่ไม่ถูกต้อง" ฉันติดตามลิงก์แล้วและฉันไม่เห็นข้อสันนิษฐานที่ไม่ถูกต้อง มันบอกอย่างชัดเจนว่า: "ถ้าใช้เมล็ดเดียวกันซ้ำหลายครั้งหมายเลขชุดเดียวกันจะถูกสร้างขึ้น"
Kyralessa

@Kyralessa "การใช้งานตัวสร้างตัวเลขสุ่มในคลาส Random ไม่รับประกันว่าจะยังคงเหมือนเดิมใน. NET Framework เวอร์ชันหลัก" ดังนั้นจึงไม่ใช่เรื่องใหญ่ แต่ยังเป็นสิ่งที่ควรพิจารณา
dlras2

4
@Kyralessa ฉันพลาดครึ่งหนึ่งที่สำคัญของคำกล่าวนั้น: "ดังนั้นรหัสแอปพลิเคชันของคุณไม่ควรถือว่าเมล็ดเดียวกันจะส่งผลให้มีการสุ่มหลอกแบบเดียวกันใน. NET Framework รุ่นต่าง ๆ "
dlras2

คำตอบ:


102

ฉันไม่คิดว่าการทดสอบหน่วยเป็นเครื่องมือที่เหมาะสมสำหรับการทดสอบแบบแผน การทดสอบหน่วยควรเรียกใช้วิธีการและทดสอบค่าที่ส่งคืน (หรือสถานะวัตถุ) กับค่าที่คาดไว้ ปัญหาของการทดสอบแบบแผนคือไม่มีค่าที่คาดหวังสำหรับสิ่งที่คุณต้องการทดสอบ คุณสามารถทดสอบด้วยเมล็ดที่กำหนด แต่นั่นทดสอบการทำซ้ำเท่านั้น มันไม่ได้ให้วิธีการวัดว่าการกระจายแบบสุ่มนั้นเป็นอย่างไรหรือถ้ามันเป็นการสุ่มเลย

โชคดีที่มีจำนวนมากของการทดสอบทางสถิติคุณสามารถเรียกใช้เช่นมิจฉาทิฐิแบตเตอรี่ของการทดสอบตามบุญตามกรรม ดูสิ่งนี้ด้วย:

  1. วิธีการทดสอบเครื่องกำเนิดเลขสุ่มหลอก?

    • Steve Jessopแนะนำให้คุณค้นหาการใช้งานของอัลกอริทึม RNG เดียวกันกับที่คุณใช้และเปรียบเทียบผลลัพธ์กับเมล็ดที่เลือกกับการใช้งานของคุณเอง
    • Greg HewgillแนะนำชุดการทดสอบทางสถิติของENT
    • John D. Cookหมายถึงผู้อ่านถึงบทความ CodeProject ของเขาSimple Random Number Generationซึ่งรวมถึงการทดสอบ Kolmogorov-Smirnov ที่กล่าวถึงในเล่ม 2 ของ Donald Knuth ซึ่งเป็นอัลกอริธึมเชิงปริมาณ
    • หลายคนแนะนำให้ทำการทดสอบว่าการแจกแจงของตัวเลขที่สร้างนั้นเป็นแบบทดสอบ Chi-squared และการทดสอบที่ค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐานอยู่ในช่วงที่คาดหวัง (โปรดทราบว่าการทดสอบการแจกแจงเพียงอย่างเดียวนั้นไม่เพียงพอ [1,2,3,4,5,6,7,8] เป็นการแจกแจงแบบสม่ำเสมอ แต่มันไม่สุ่มแน่นอน)
  2. การทดสอบหน่วยด้วยฟังก์ชันที่ส่งคืนผลลัพธ์แบบสุ่ม

    • Brian Genisioชี้ให้เห็นว่าการเยาะเย้ย RNG ของคุณเป็นตัวเลือกหนึ่งสำหรับการทดสอบซ้ำและให้รหัสตัวอย่าง C #
    • อีกหลายคนชี้ไปที่การใช้ค่าเมล็ดคงที่สำหรับการทำซ้ำและการทดสอบอย่างง่ายสำหรับการแจกแจงแบบสม่ำเสมอ Chi-squared ฯลฯ
  3. การทดสอบหน่วยการสุ่มเป็นบทความวิกิที่พูดถึงความท้าทายหลายอย่างที่สัมผัสอยู่แล้วเมื่อพยายามที่จะทดสอบสิ่งที่เป็นธรรมชาติของมันไม่สามารถทำซ้ำได้ หนึ่งบิตที่น่าสนใจที่ฉันได้รับจากมันคือ:

    ฉันเคยเห็น winzip ใช้เป็นเครื่องมือในการวัดแบบแผนของไฟล์ค่าก่อนหน้านี้ (เห็นได้ชัดว่าขนาดเล็กมันสามารถบีบอัดไฟล์ที่สุ่มน้อยมันเป็น)


ชุดทดสอบอีกที่ดีสำหรับการสุ่มทางสถิติคือ 'Ent' พบได้ที่fourmilab.ch/random

1
คุณสามารถสรุปลิงค์ที่คุณโพสต์ไว้เพื่อความสมบูรณ์ของคำตอบได้หรือไม่?
dlras2

@DanRasmussen แน่นอนฉันจะมีเวลาทำอย่างนั้นในช่วงสุดสัปดาห์
Bill the Lizard

4
“ ปัญหากับ…การสุ่มคือไม่มีค่าที่คาดหวัง…” - วิธีที่น่าขบขันเนื่องจาก“ ค่าที่คาดหวัง” เป็นคำที่กำหนดชัดเจนในสถิติ และในขณะที่นี่ไม่ใช่สิ่งที่คุณหมายถึงมันจะแนะนำวิธีการแก้ปัญหาที่ถูกต้อง: การใช้คุณสมบัติที่เป็นที่รู้จักของการแจกแจงเชิงสถิติควบคู่ไปกับการสุ่มตัวอย่างและการทดสอบทางสถิติเพื่อพิจารณาว่าอัลกอริทึมทำงานด้วยความน่าจะเป็นสูง ใช่ว่าไม่ได้เป็นหน่วยทดสอบคลาสสิก แต่ผมอยากจะพูดถึงมันตั้งแต่ในกรณีที่ง่ายที่สุดก็แค่มองไปที่การกระจายของ ... ที่ค่าที่คาดหวัง
Konrad Rudolph

2
มีรุ่นปรับปรุงใหม่ของ Diehard Battery of Tests of Randomness ที่ Dieharder ซึ่งรวมถึงชุดทดสอบสถิติ (STS) ที่พัฒนาโดยสถาบันมาตรฐานและเทคโนโลยีแห่งชาติ (NIST) พร้อมใช้งานใน Ubuntu และ distros อื่น ๆ น่าจะเป็น: phy.duke.edu/~rgb/General/dieharder.php
nealmcb

21

1. หน่วยทดสอบอัลกอริทึมของคุณ

สำหรับคำถามแรกฉันจะสร้างคลาสปลอมที่คุณป้อนหมายเลขสุ่มตามลำดับซึ่งคุณทราบผลลัพธ์ของอัลกอริทึมของคุณ วิธีนี้ทำให้คุณมั่นใจได้ว่าอัลกอริธึมที่คุณสร้างขึ้นบนฟังก์ชั่นการสุ่มของคุณทำงาน ดังนั้นสิ่งที่ตามแนวของ:

Random r = new RandomStub([1,3,5,3,1,2]);
r.random(); //returns 1
r.random(); //returns 3
...

2. ดูว่าฟังก์ชั่นการสุ่มของคุณเหมาะสมหรือไม่

ในการทดสอบหน่วยคุณควรเพิ่มการทดสอบที่เรียกใช้หลายครั้งและยืนยันว่าผลลัพธ์

  • อยู่ในขอบเขตที่คุณตั้งค่าไว้ (เช่นลูกเต๋าจะอยู่ระหว่าง 1 ถึง 6) และ
  • แสดงการแจกแจงที่สมเหตุสมผล (ทำการทดสอบหลายครั้งและดูว่าการกระจายอยู่ภายใน x% ของสิ่งที่คุณคาดหวังหรือไม่เช่นสำหรับทอยลูกเต๋าคุณจะเห็นว่ามี2ค่าระหว่าง 10% ถึง 20% (1/6 = 16.67%) ของ เวลาที่คุณรีด 1,000 ครั้ง)

3. การทดสอบการรวมสำหรับอัลกอริทึมและฟังก์ชั่นแบบสุ่ม

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

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

จากประสบการณ์ (ฉันเขียนอัลกอริธึมทางพันธุกรรม) ฉันจะบอกว่ารวมการทดสอบหน่วยของอัลกอริทึมของคุณการทดสอบการกระจายของฟังก์ชั่นการสุ่มของคุณและการทดสอบการรวมเป็นวิธีที่จะไป


14

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

การทดสอบที่เหมาะสมสำหรับ PRNG จะเกี่ยวข้องกับการรันอย่างน้อย 100 ครั้งจากนั้นตรวจสอบการกระจายของเอาต์พุต (ซึ่งเป็นคำตอบโดยตรงไปยังส่วนที่สองของคำถาม)

คำตอบสำหรับคำถามแรกเกือบจะเหมือนกัน: รันการทดสอบประมาณ 100 ครั้งด้วย {1, 2, ... , n} และนับจำนวนครั้งที่แต่ละองค์ประกอบได้รับในแต่ละตำแหน่ง พวกเขาควรจะเท่าเทียมกันอย่างคร่าว ๆ หากวิธีการสลับใด ๆ ที่ดี

สิ่งที่แตกต่างอย่างสิ้นเชิงคือวิธีทดสอบ PRNG เกรดการเข้ารหัส นี่เป็นเรื่องที่คุณไม่ควรอยู่เว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่ ผู้คนรู้จักทำลาย (อ่าน: เปิดหลุมหายนะ) cryptosystem ที่ดีด้วยการ 'เพิ่มประสิทธิภาพ' หรือการแก้ไขเล็กน้อย

แก้ไข: ฉันได้อ่านคำถามอย่างละเอียดคำตอบยอดเยี่ยมและของฉันเอง ในขณะที่คะแนนที่ฉันยังคงยืนอยู่ฉันจะตอบ Bill The Lizard ที่สอง การทดสอบหน่วยเป็นบูลีนในลักษณะของพวกเขา - พวกเขาล้มเหลวหรือพวกเขาประสบความสำเร็จและดังนั้นจึงไม่เหมาะสำหรับการทดสอบ "วิธีที่ดี" เป็นคุณสมบัติของ PRNG (หรือวิธีการใช้ PRNG) เนื่องจากคำตอบของคำถามนี้จะเป็นเชิงปริมาณ มากกว่าขั้วโลก


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

@octern ขอบคุณฉันไม่ทราบว่าฉันจะได้เขียนไว้ว่า ... มันเป็นอย่างสมบูรณ์ผิดจนถึงขณะนี้ ...
K.Steff

6

มีสองส่วนดังนี้: การทดสอบการสุ่มและการทดสอบสิ่งต่าง ๆ ที่ใช้การสุ่ม

การสุ่มทดสอบค่อนข้างตรงไปตรงมา คุณตรวจสอบว่าช่วงเวลาของตัวสร้างตัวเลขสุ่มเป็นอย่างที่คุณคาดหวังว่าจะเป็น (สำหรับตัวอย่างไม่กี่ตัวอย่างที่ใช้เมล็ดพันธุ์แบบสุ่มไม่กี่ตัวภายในขีด จำกัด ) และการกระจายของผลลัพธ์ในขนาดตัวอย่างขนาดใหญ่เป็นไปตามที่คุณคาดหวัง มันจะเป็น (ภายในเกณฑ์)

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


6

ให้มันทำงานพวงของครั้งและเห็นภาพข้อมูลของคุณ

นี่คือตัวอย่างของการสลับจากCoding Horrorคุณจะเห็นว่าอัลกอริทึมนั้นใช้ได้หรือไม่:

ป้อนคำอธิบายรูปภาพที่นี่

เป็นเรื่องง่ายที่จะเห็นว่าทุกรายการที่เป็นไปได้จะถูกส่งคืนอย่างน้อยหนึ่งครั้ง (ขอบเขตเป็นปกติ) และการแจกแจงนั้นตกลง


1
การสร้างภาพ +1 เป็นกุญแจสำคัญ ฉันชอบตัวอย่างที่มีรูปของนกเพนกวินในส่วน ECB ของบทความบล็อกตัวเลข ) ซอฟต์แวร์อัตโนมัติไม่ค่อยสามารถตรวจจับระเบียบดังกล่าวได้
Maksee

ใช่มั้ย? จุดประสงค์ของการสร้างภาพข้อมูลนั้นคือการแสดงให้เห็นว่าการกระจายนั้นไม่เป็นไร อัลกอริทึมแบบสุ่มไร้เดียงสาทำให้การสั่งซื้อบางอย่างมีแนวโน้มมากกว่าคำสั่งซื้ออื่น ๆ สังเกตว่าแท่งเหล็กยาว 2341, 2314, 2143 และ 1342 นั้นไกลไปเท่าใด
hvd

4

พอยน์เตอร์ทั่วไปฉันพบว่ามีประโยชน์เมื่อจัดการกับโค้ดที่รับอินพุตแบบสุ่ม: ตรวจสอบกรณีขอบของการสุ่มที่คาดหวัง (ค่าสูงสุดและค่าต่ำสุดและค่าสูงสุด + 1 และ min-1 ถ้ามี) ตรวจสอบสถานที่ (บน, ด้านบน, และด้านล่าง) ที่ตัวเลขมีจุดผัน (เช่น -1, 0, 1, หรือมากกว่า 1, น้อยกว่า 1 และไม่เป็นลบสำหรับกรณีที่ค่าเศษส่วนอาจทำให้ฟังก์ชันยุ่งเหยิง) ตรวจสอบสถานที่บางแห่งนอกอินพุตที่ได้รับอนุญาต ตรวจสอบกรณีทั่วไปไม่กี่ คุณยังสามารถเพิ่มอินพุตแบบสุ่มได้ แต่สำหรับการทดสอบหน่วยที่มีผลข้างเคียงที่ไม่พึงประสงค์ที่ค่าเดียวกันไม่ได้อยู่ภายใต้การทดสอบในแต่ละครั้งที่ทำการทดสอบ S หรือ somesuch)

สำหรับการทดสอบผลลัพธ์ของฟังก์ชั่นแบบสุ่มสิ่งสำคัญคือการระบุเป้าหมาย ในกรณีของบัตรมีเป้าหมายเพื่อทดสอบความสม่ำเสมอของเครื่องกำเนิดสุ่ม 0-1 เพื่อตรวจสอบว่าไพ่ 52 ใบปรากฏในผลลัพธ์หรือเป้าหมายอื่น ๆ (อาจเป็นรายการทั้งหมดนี้หรือมากกว่า)?

ในตัวอย่างที่เฉพาะเจาะจงคุณต้องสมมติว่าตัวสร้างตัวเลขสุ่มของคุณนั้นทึบ (เช่นเดียวกับที่มันไม่เหมาะสมที่จะทดสอบหน่วย syscall หรือ malloc- เว้นแต่ว่าคุณเขียน OS) อาจเป็นประโยชน์ในการวัดตัวสร้างตัวเลขสุ่ม แต่เป้าหมายของคุณคือไม่ต้องเขียนตัวสร้างแบบสุ่มเพียงเพื่อดูว่าคุณได้รับไพ่ 52 ใบในแต่ละครั้งและพวกเขาเปลี่ยนลำดับ

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


4

คุณสามารถพึ่งพาเครื่องกำเนิดจำนวนสุ่มที่ปลอดภัย

ฉันเพิ่งมีความคิดที่น่ากลัว: คุณไม่ได้เขียนตัวสร้างตัวเลขสุ่มของคุณเองคุณ?

สมมติว่าคุณไม่ใช่คุณควรทดสอบรหัสที่คุณรับผิดชอบไม่ใช่รหัสของคนอื่น (เช่นSecureRandomการนำกรอบงานไปใช้)

ทดสอบรหัสของคุณ

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

เห็นได้ชัดว่าคุณจะตรวจสอบเงื่อนไขของขอบและตรวจสอบให้แน่ใจว่าการสับจะเกิดขึ้นตรงตามอัลกอริทึมของคุณที่กำหนดอินพุตที่เหมาะสม

ทดสอบเครื่องกำเนิดเลขสุ่มที่ปลอดภัย

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


1

คุณจะไม่มีทางแน่ใจ 100% ดังนั้นสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือมีความเป็นไปได้ที่ตัวเลขจะถูกสุ่ม เลือกความน่าจะเป็น - บอกว่าตัวอย่างของตัวเลขหรือรายการจะเกิดขึ้น x คูณหนึ่งล้านตัวอย่างภายในระยะขอบของข้อผิดพลาด ดำเนินการเป็นล้านครั้งและดูว่าอยู่ในระยะขอบหรือไม่ โชคดีที่คอมพิวเตอร์ทำให้สิ่งนี้ง่ายต่อการทำ


แต่การทดสอบหน่วยเช่นนี้ถือว่าเป็นแนวปฏิบัติที่ดี .. ฉันคิดเสมอว่าการทดสอบหน่วยควรจะง่ายที่สุดเท่าที่จะทำได้: ไม่มีลูปกิ่งไม้หรือสิ่งอื่นใดที่สามารถหลีกเลี่ยงได้
dlras2

4
การทดสอบหน่วยควรจะถูกต้อง ถ้ามันใช้เวลาแตกกิ่งลูปเรียกซ้ำ - นั่นคือราคา คุณไม่สามารถทดสอบหน่วยคลาสที่มีความซับซ้อนและได้รับการปรับให้เหมาะสมสูงสุดด้วยการทดสอบหน่วยแบบหนึ่งซับ ฉันใช้อัลกอริทึมของ Dijkstra เพื่อทดสอบหน่วยในชั้นเรียนหนึ่งครั้ง
K.Steff

3
@ K.Steff ว้าว คุณทำการทดสอบหน่วยการทดสอบของคุณเพื่อตรวจสอบว่าอัลกอริทึม Dijkstra ถูกต้องหรือไม่?
Winston Ewert

จุดดีตามความเป็นจริง - ใช่ แต่คราวนี้มีการทดสอบ 'เล็กน้อย' พวกเขายังทำการทดสอบหน่วยสำหรับโปรแกรมต้นฉบับ (A *) ด้วย ฉันคิดว่านั่นเป็นวิธีปฏิบัติที่ดีจริงๆ - ทดสอบอัลกอริทึมที่รวดเร็วอีกครั้งซึ่งจะทำให้การใช้งานอ่อนแอ (แต่ถูกต้อง)
K.Steff

1

เพื่อทดสอบว่าแหล่งที่มาของตัวเลขสุ่มกำลังสร้างสิ่งที่อย่างน้อยมีลักษณะของการสุ่มฉันจะมีการทดสอบสร้างลำดับของไบต์ที่ค่อนข้างใหญ่เขียนมันลงในไฟล์ชั่วคราวจากนั้นใช้เครื่องมือentของ Fourmilab ให้ป้อนสวิตช์ -t (terse) ดังนั้นมันจะสร้าง CSV ที่ง่ายต่อการแยกวิเคราะห์ จากนั้นตรวจสอบหมายเลขต่าง ๆ เพื่อดูว่าพวกเขา "ดี"

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

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


1

กรณีที่ 1: ทดสอบการสุ่มเพลง:

ลองพิจารณาอาเรย์ [0, 1, 2, 3, 4, 5], สับมันแล้วจะเกิดอะไรขึ้น? สิ่งที่ปกติ: a) ไม่มีการสลับเลย b) การสับ 1-5 แต่ไม่ใช่ 0, การสับแบบ 0-4 แต่ไม่ใช่ 5, การสลับแบบสุ่มและสร้างรูปแบบเดียวกันเสมอ ...

การทดสอบหนึ่งรายการเพื่อจับพวกเขาทั้งหมด:

สุ่ม 100 ครั้งเพิ่มค่าในแต่ละช่อง ผลรวมของแต่ละช่องควรใกล้เคียงกัน สามารถคำนวณค่าเฉลี่ย / Stddev ได้ (5 + 0) /2=2.5, 100 * 2.5 = 25 ตัวอย่างเช่นค่าที่คาดไว้คือ 25

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

มันสามารถล้มเหลว 3 ครั้งติดต่อกัน? บางทีคุณควรลองเสี่ยงโชคที่ลอตเตอรี

กรณีที่ 2: ทอยลูกเต๋า

คำถามลูกเต๋าเป็นคำถามเดียวกัน โยนลูกเต๋า 6000 ครั้ง

for (i in 0 to 6000) 
    ++slot [Random.nextInt (6)];
return (slot.max - slot.min) < threshold;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.