rand#
מחזיר מספר פסאודו־אקראי בנקודה צפה בטווח חצי־פתוח [0, EXPR).
rand שולף את הערך הבא מזרם המספרים הפסאודו־אקראיים של המפענח ומשנה את קנה המידה ל־0 <= n < EXPR. התוצאה היא מספר Perl רגיל (double), אף פעם לא מספר שלם בעצמה - עטפו עם int כאשר אתם רוצים מספר שלם. EXPR הוא אופציונלי וברירת המחדל היא 1, כך ש־rand חשוף מניב float ב־[0, 1).
תקציר#
rand EXPR
rand
מה מקבלים בחזרה#
float בדיוק כפול n עם 0 <= n < EXPR. הגבול העליון אינו כלול: rand(6) אף פעם אינו מחזיר 6, רק ערכים נמוכים ממש ממנו. לתוצאת מספר שלם, הרכיבו עם int:
my $die = int(rand(6)) + 1; # 1..6
ההתפלגות היא (בקירוב) אחידה לאורך הטווח. rand הוא אופרטור סקלרי - הוא מחזיר ערך אחד לכל קריאה, ללא קשר להקשר.
מצב גלובלי שהוא נוגע בו#
rand צורך את מצב ה־PRNG הפנימי של המפענח, המשותף עם srand. שני כללים נובעים מכך:
Autoseeding: הקריאה הראשונה ל־
randבתוכנית קוראת אוטומטית ל־srandאם טרם עשיתם זאת. הזרע נבחר מאנטרופיה ברמת התהליך, ולכן תוכניות לא־מזורעות מפיקות זרם שונה בכל ריצה.זרם משותף: כל קריאת
randעוקבת - בכל מקום בתוכנית, בכל מודול - שולפת מאותה סדרה. קריאה ל־srand($seed)עם זרע קבוע הופכת את הסדרה הזו לדטרמיניסטית וניתנת לשחזור, וזה מה שאתם רוצים ל־test fixtures ולדיבוג. קריאה ל־srand()ללא ארגומנט מזריעה מחדש מאנטרופיה.
אין בידוד לכל־thread או לכל־תחום. אם אתם זקוקים לזרם עצמאי לפיסת קוד אחת, אל תשתמשו ב־rand; פנו למודול מחולל ייעודי.
דוגמאות#
שליפה בסיסית ב־[0, 1):
my $u = rand(); # e.g. 0.4173...
הטלת קוביה - הניב הקנוני int(rand(N)) + 1:
my $roll = int(rand(6)) + 1; # 1..6
אלמנט אקראי של מערך:
my @colors = qw(red green blue yellow);
my $pick = $colors[ rand @colors ];
rand @colors משתמש באורך המערך (הקשר סקלר נכפה על־ידי ה־prototype של rand), כך שזה עובד לכל גודל מערך.
זרם ניתן לשחזור - קבעו את הזרע למבחנים:
srand(42);
my @sample = map { rand() } 1..5; # same five numbers every run
ניב ערבוב בשורה אחת. קריא, אבל מוטה - sort משווה זוגות יותר מפעם אחת, ו־rand() חד־פעמי לכל השוואה אינו מייצר תמורה אחידה:
my @shuffled = sort { rand() <=> 0.5 } @list; # biased; do not use
לערבוב הוגן, השתמשו ב־List::Util::shuffle:
use List::Util qw(shuffle);
my @shuffled = shuffle @list;
הדמיית מטבע משוקלל - שימו לב שהגבול העליון הלא־כולל אומר ש־rand() < 0.3 יורה בהסתברות בדיוק 0.3:
my $heads = rand() < 0.3 ? "heads" : "tails";
מקרי קצה#
EXPRהוא0: מטופל כ־1, ולכןrand(0)מתנהג כמוrand(1). זוהי התנהגות מתועדת של ה־upstream והיא נשמרת כאן, אך זוהי מוזרות היסטורית - אל תסתמכו עליה בקוד חדש.EXPRשלילי: התוצאה אינה מוגדרת בפועל - אתם עשויים לקבל0, אתם עשויים לקבל float שלילי, וההתנהגות אינה ניידת בין גרסאות Perl. אם אתם רוצים ערך ב־[-N, 0), כתבוrand($n) - $nבמפורש.EXPRהואundef: מומר למחרוזת ל־"", מומר מספרית ל־0, ולכן מתנהג כמוrand(0)→rand(1). תחתuse warningsתקבלו אזהרתuninitialized.EXPRאינו מספרי: ההמרה הרגילה מסקלר למספר חלה.rand("3abc")הואrand(3)עם אזהרה לא־מספרית.אינו מאובטח קריפטוגרפית:
randמשתמש ב־PRNG מהיר המתאים לסימולציה, ערבוב, ו־test fixtures. הוא אינו מתאים ל־session tokens, password salts, חומר מפתח, או כל ערך רגיש מבחינה אבטחתית. עבור אלה, קראו מ־/dev/urandomישירות או השתמשו ב־Crypt::URandom/Crypt::PRNG.התנהגות thread/fork: לאחר
fork, הן ההורה והן הילד יורשים את אותו מצב PRNG ויפיקו את אותו זרם אלא אם כן אחד מהם קורא ל־srand()כדי להזריע מחדש. foot-gun שכיח בשרתי pre-forking - הזריעו בילד.EXPRגדול: המחולל מפיק 48 ביטים של אקראיות לכל שליפה; עבורEXPRקרוב או מעל2**48, הפלט אינו מתפלג עוד בעידון לאורך הטווח. עבור רוחבים קריפטוגרפיים אינכם צריכים להשתמש ב־randבכל מקרה (ראו למעלה).
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
srand- הזרעת ה־PRNG במפורש לשחזוריות, או הזרעה מחדש בילד מפוצלint- קטיעת תוצאתrandלכיוון אפס כדי לקבל מספר שלם אחיד ב־[0, N)List::Util::shuffle- ערבוב Fisher-Yates הוגן; העדיפו זאת על פני הניבsort { rand() <=> 0.5 }Crypt::URandom- בתים אקראיים מאובטחים קריפטוגרפית ממקור האנטרופיה של מערכת ההפעלה; השתמשו בזה ל־tokens, salts וחומר מפתחCrypt::PRNG- PRNG מאובטח קריפטוגרפית עם API עשיר כאשר אתם זקוקים ליותר מבתים גולמיים