יצירת מספרים אקראיים בג'אווה

1. סקירה כללית

במדריך זה נחקור דרכים שונות ליצור מספרים אקראיים ב- Java.

2. שימוש ב- Java API

ממשק ה- API של Java מספק לנו מספר דרכים להשיג את מטרתנו. בואו נראה כמה מהם.

2.1. java.lang.Math

ה אַקרַאִי שיטת ה- מתמטיקה השיעור יחזיר א לְהַכפִּיל ערך בטווח שבין 0.0 (כולל) ל- 1.0 (בלעדי). בואו נראה כיצד נשתמש בו בכדי לקבל מספר אקראי בתחום נתון שהוגדר על ידי דקה ו מקסימום:

int randomWithMathRandom = (int) ((Math.random () * (max - min)) + min);

2.2. java.util.Random

לפני Java 1.7, הדרך הפופולרית ביותר ליצור מספרים אקראיים הייתה שימוש הבא. היו שתי דרכים להשתמש בשיטה זו, עם ובלי פרמטרים. הקריאה ללא פרמטר מחזירה את ה- int ערכים בהסתברות שווה בערך. לכן סביר מאוד שנקבל מספרים שליליים:

אקראי אקראי = אקראי חדש (); int randomWithNextInt = random.nextInt ();

אם אנו משתמשים ב- netxInt קריאה עם כָּרוּך פרמטר, נקבל מספרים בטווח:

int randomWintNextIntWithinARange = random.nextInt (max - min) + min;

זה ייתן לנו מספר בין 0 (כולל) לפרמטר (בלעדי). לכן, הפרמטר הקשור חייב להיות גדול מ- 0. אחרת נקבל java.lang.IllegalArgumentException.

ג'אווה 8 הציגה את החדש ints שיטות שמחזירות א java.util.stream.IntStream. בואו נראה איך להשתמש בהם.

ה ints שיטה ללא פרמטרים מחזירה זרם בלתי מוגבל של int ערכים:

IntStream unlimitedIntStream = random.ints ();

אנו יכולים גם להעביר פרמטר יחיד להגבלת גודל הזרם:

IntStream limitedIntStream = random.ints (streamSize);

וכמובן, אנו יכולים להגדיר את המקסימום והמינימום עבור הטווח שנוצר:

IntStream limitedIntStreamWithinARange = random.ints (streamSize, min, max);

2.3. java.util.concurrent.ThreadLocalRandom

גרסת Java 1.7 הביאה לנו דרך חדשה ויעילה יותר לייצר מספרים אקראיים דרך ה- ThreadLocalRandom מעמד. לזה יש שלושה הבדלים חשובים מה- אַקרַאִי מעמד:

  • איננו צריכים ליזום במפורש מופע חדש של ThreadLocalRandom. זה עוזר לנו להימנע מטעויות ביצירת המון מקרים חסרי תועלת ובזבוז זמן אספן האשפה
  • אנחנו לא יכולים להגדיר את הזרע עבור ThreadLocalRandom, שעלול להוביל לבעיה אמיתית. אם עלינו לקבוע את הזרע, עלינו להימנע מדרך זו ליצירת מספרים אקראיים
  • אַקרַאִי הכיתה לא מתפקדת טוב בסביבות מרובי הליכי משנה

עכשיו, בואו נראה איך זה עובד:

int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current (). nextInt (דקות, מקסימום);

עם Java 8 ומעלה, יש לנו אפשרויות חדשות. ראשית, יש לנו שתי וריאציות עבור הבא שיטה:

int randomWithThreadLocalRandom = ThreadLocalRandom.current (). nextInt (); int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current (). nextInt (max);

שנית, וחשוב מכך, אנו יכולים להשתמש ב- ints שיטה:

IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current (). Ints ();

2.4. java.util.SplittableRandom

ג'אווה 8 הביאה לנו גם גנרטור מהיר באמת - SplittableRandom מעמד.

כפי שאנו רואים ב- JavaDoc, זהו מחולל לשימוש בחישובים מקבילים. חשוב לדעת שהמקרים אינם בטוחים בחוטים. לכן עלינו לדאוג לשימוש בשיעור זה.

יש לנו את הבא ו ints שיטות. עם הבא אנו יכולים להגדיר ישירות את הטווח העליון והתחתון באמצעות שני הפרמטרים הקריאה:

SplittableRandom splittableRandom = SplittableRandom חדש (); int randomWithSplittableRandom = splittableRandom.nextInt (min, max);

דרך זו באמצעות בדיקות ש- מקסימום הפרמטר גדול מ- דקה. אחרת, נקבל IllegalArgumentException. עם זאת, זה לא בודק אם אנחנו עובדים עם מספרים חיוביים או שליליים. לכן, כל אחד מהפרמטרים יכול להיות שלילי. כמו כן, יש לנו קריאות פרמטר אחד ואפס. אלה עובדים באותו אופן כפי שתיארנו בעבר.

יש לנו את ints גם שיטות. משמעות הדבר היא שנוכל בקלות להשיג זרם של int ערכים. לשם הבהרה, אנו יכולים לבחור בזרם מוגבל או בלתי מוגבל. עבור זרם מוגבל, אנו יכולים להגדיר את החלק העליון והתחתון לטווח ייצור המספרים:

IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints (streamSize, min, max);

2.5. java.security.SecureRandom

אם יש לנו יישומים רגישים לאבטחה, עלינו לשקול להשתמש SecureRandom. זהו גנרטור חזק מבחינה קריפטוגרפית. מקרים שנבנו כברירת מחדל אינם משתמשים בזרעים אקראיים קריפטוגרפיים. אז עלינו:

  • הגדר את הזרע - כתוצאה מכך, הזרע לא יהיה צפוי
  • הגדר את java.util.secureRandomSeed נכס מערכת ל נָכוֹן

מעמד זה יורש מ java.util.Random. אז יש לנו את כל השיטות שראינו לעיל. לדוגמא, אם עלינו להשיג כל אחד מה- int ערכים, ואז נתקשר הבא ללא פרמטרים:

SecureRandom secureRandom = SecureRandom חדש (); int randomWithSecureRandom = secureRandom.nextInt ();

מצד שני, אם אנחנו צריכים להגדיר את הטווח, אנחנו יכולים לקרוא לזה עם ה- כָּרוּך פָּרָמֶטֶר:

int randomWithSecureRandomWithinARange = secureRandom.nextInt (max - min) + min;

עלינו לזכור שדרך השימוש הזו זורקת IllegalArgumentException אם הפרמטר אינו גדול מאפס.

3. שימוש בממשקי API של צד שלישי

כפי שראינו, ג'אווה מספקת לנו הרבה שיעורים ושיטות להפקת מספרים אקראיים. עם זאת, ישנם גם ממשקי API של צד שלישי למטרה זו.

אנו נסתכל על כמה מהם.

3.1. org.apache.commons.math3.random.RandomDataGenerator

בספריית המתמטיקה של commons ישנם הרבה גנרטורים מפרויקט Apache Commons. הקלה ביותר, וכנראה השימושית ביותר, היא RandomDataGenerator. הוא משתמש ב- ובכן -19937 ג אלגוריתם לדור האקראי. עם זאת, אנו יכולים לספק את יישום האלגוריתם שלנו.

בואו נראה איך להשתמש בזה. ראשית, עלינו להוסיף תלות:

 org.apache.commons commons-math3 3.6.1 

הגרסה האחרונה של commons-math3 ניתן למצוא ב Maven Central.

ואז נוכל להתחיל לעבוד עם זה:

RandomDataGenerator randomDataGenerator = RandomDataGenerator חדש (); int randomWithRandomDataGenerator = randomDataGenerator.nextInt (דקות, מקסימום);

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

אין ספק שמדובר באחת מביצועי מחולל המספרים האקראיים המהירים ביותר. הוא פותח במחלקה למדעי המידע באוניברסיטת מילאנו.

הספרייה זמינה גם במאגרי Maven Central. אז בואו נוסיף את התלות:

 it.unimi.dsi dsiutils 2.6.0 

מחולל זה יורש מ java.util.Random. עם זאת, אם נסתכל על JavaDoc, אנו מבינים שיש רק דרך אחת להשתמש בו - דרך ה- הבא שיטה. מעל לכל, שיטה זו זמינה רק עם הקריאות לאפס ופרמטר אחד. כל אחת מההזמנות האחרות תשתמש ישירות ב- java.util.Random שיטות.

לדוגמא, אם אנו רוצים לקבל מספר אקראי בטווח, היינו כותבים:

XoRoShiRo128PlusRandom xoroRandom = XoRoShiRo128PlusRandom חדש (); int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt (max - min) + min;

4. מסקנה

ישנן מספר דרכים ליישום יצירת מספרים אקראיים. עם זאת, אין דרך הטובה ביותר. כתוצאה מכך, עלינו לבחור את המתאים ביותר לצרכינו.

ניתן למצוא את הדוגמה המלאה ב- GitHub.