|
||||
|
||||
שלום, כתבתי לפני כשנה מחולל של מספרים אקריים בספת PHP משום שהמחולל המובנה גרוע עד מאוד. <?php המחולל שלי מבטיח שלא יהיו חזרות נשנות, את פשטותו ואת מהירותו. אני מתבסס על חילוק של שני מספרים ראשוניים שהאחד הוא מ'ס השניות מאז 1970 (UNIX time) והשני הוא מ'ס המילישניות ברגע (בשנייה) הנוכחי(ת); והנוסחה של Euler אשר הופכת כל מספר לראשוני.function frand($to=100, $from=0, $if_float=0, $if_abs=true, $if_trace=false) { $to++; $tracer = microtime(); list($micro, $sec) = explode(" ", $tracer); $tracer = " - $tracer"; $FLOAT = "; $MUL = 1; if ($if_float > 0) {$to--; $FLOAT = '.'.frand(pow(10, $if_float));} if ($if_trace === false) { $tracer = ";} if ($if_abs === false) { $MUL = frand(2) == 0 ? -1 : 1; } $micro = pow($micro, 2) + $micro +41; // according to Euler's formula $sec = pow($sec, 2) + $sec +41; $precisement = strlen($to) +substr($micro, 0, 2) +2; $ret = sprintf("[%.{$precisement}f]",($micro/$sec)); return ((((substr($ret, (strlen($to) > 3 ? (5+strlen($to))*(-1) : -5)) % ($to-$from)) + $from).$FLOAT)*$MUL).$tracer; } ?> כל הקטצ' הוא בזה שאם מפעילים את הארגומנט האחרון if_trace$ אז ניתן לראות מאילו מספרים חולל המ'ס שנפלט. זאת אומרת שאם יודעים באיזו שניה ומילישניה חולל המ'ס, אז ניתן לחולל את המ'ס הזה בדיוק בעת הצורך. משמע, שאם אני שולח לך סדרה של מספרים "אקראיים", תוכל לנתב אותם לשני צורות - סדרה של שניות ומילישניות (ע"י חישוב מסויים של כמה מילישניות עוברות בין מ'ס למ'ס במחשב מסויים); או להפך, אני שולח לך את השניה והמילישניה הראשונה והאחרונה (וע"י אותו החישוב של פעולות המחשב) תוכל לקבל את הסדרה לעיל. :) |
|
||||
|
||||
אני מציע לך מאוד להיזהר. הנוסחה n^2+n+41 לא "הופכת כל מספר לראשוני". עבור n=40 תקבל 41 בריבוע. באופן כללי לא קיים פולינום שלכל ערך טבעי שמציבים בו נותן מספר ראשוני - תמיד אפשר להנדס קלט שיחזיר תוצאה פריקה. |
|
||||
|
||||
הייתי אומר, בזהירות, שזו הבעייה הכי קטנה של המחולל הזה. איני סבור שהוא יעבור איזשהו מבחן אקראיות פשוט המביט בזוגות עוקבים. קוד פשוט וקצר עבור מחולל חזק מאוד יש כאן: (יש לרדת במורד הפתיל עד להודעה של Marsaglia). לדעתו של זה האחרון מחולל זה עדיף על Mersenne Twister הפופולרי. אם PHP תומך בשלמים עם 64 ביטים, לא צריך להיות כל קושי לתרגם את הקוד הזה ל-PHP. כדי לאתחל את המערך Q אפשר להשתמש במחולל פשוט כלשהו עם seed של תו הזמן. |
|
||||
|
||||
אני מודה שלא טרחתי לקרוא את הקוד של המחולל, רק הסתקרנתי מהי אותה נוסחה של Euler אשר הופכת כל מספר לראשוני. |
|
||||
|
||||
תודה על ההערה, אבל עוד לא ניתקלתי ב N1 = 40 , וצריך לא לשכוח שיש N2 התלוי ב ()time שלא חוזר על עצמו. אתה כמובן צודק בקשר ל-40 הזה, אבל ישנם עוד כמה נוסחאות כאלה שאמורות להפוך מ'ס לראשוני, או שפשוט אפשר לחבר לN1 וN2, את המ'ס 42 ליתר ביטחון. רק שלוש הערות לי אליך, כבודו : 1. המחולל המובנה של PHP כה עלוב שבשימוש נקי (בלי פונקציות פנימיות, כגון, (()rand(rand, וכדומה) יכול לפלוט חצי סדרה בת 10 איברים כאותו איבר (3,3,3,3,3,3,2,2,1,7 לדוגמה). 2. חשבתי ובניתי אותו לבד. פרסמתיו באתר http://www.phpclasses.org/browse/package/4974.html והורידו אותו 4574 אנשים בלי קשר לאתר זה ו203 אנשים הרשומים בו. 3. אני חושב שזה המחולל היחיד, שלפחות אני מקיר, שעובד עם מספרים שלמים, שברים עשרוניים, חיוביים ושליליים. |
|
||||
|
||||
אני חושב שאפסיק כאן. אני לא רוצה עוד דיון 1571. |
|
||||
|
||||
צר לי מאוד שהבנת אותי בדרך כה מבזה הוד גאונותך. אני מבין שסלדתי קצת מהנושא, אבל רק רציתי להראות מחולל מספרים אקראיים ע"י מטמטיקה פשוטה שיכול בגאווה לעמוד מול כל מחולל אחר. כמובן שאי אפשר בוודעות לדעת מה יצר מ'ס זה או אחר, מכיוון שזה אותו הדבר כצם לשאול איזה מ'ס אחרי מודולו 2 פלט 0 ? אני לא מתיימר להיות גאון או חכם ממישהו. אבל עדיין, איך אנשים כותבים דוקטורטים חדשים מידי שנה (ויש בינהם נושאים מרתקים וחדשניים במיוחד), חידות ששנים ארוכות הרתיעו מטמטיקאים (כמו למשל "תאורמת פרמה") נפתרות, ואף אחד לא מתחיל להיתבלבל והמטמטיקה נשארת במקומה אם לא מתפתחת הלאה. אם נותנים לך פתרון קצר יותר משלך לאותה הבעיה\שאלה לפעמים רצויי לאמץ אותו, ולא לעמוד על שלך כמו תייש ולהצהיר שגם התשובה שלך נותנת פתרון. ברור שאם יש בידיך פתרון אז הוא נכון, אבל אם הוא יותר ארוך ומסובך אז למה תהיתקע עליו ? אני מצתער אם העלבתי את כבודו, אבל גם כבודו העליב אותי. |
|
||||
|
||||
שמור את הצער למקרי חירום, אתה קטן מכדי להעליב את גדי. |
|
||||
|
||||
מהו מבחינתך מחולל מספרים אקראיים טוב? אילו תכונות צריכות להיות לו? |
|
||||
|
||||
1. שיהיה מהיר ככל האפשר. 2. שבקוד יהיה קצר ככל האפשר. 3. שבפלט לא יהיו שני מספרים זהים אחד אחרי השני. |
|
||||
|
||||
לגביי 3., אלא אם מ'ס האפשרויות קטן במיוחד, סמו סדרות בינריות וכדומה. |
|
||||
|
||||
(1) ו־(2) הן דרישות של יעילות. אני חושב שתסכים איתי שהקוד צריך קודם כל לעבוד היטב. לגבי (3), אני חושב שהניסוח שלך פשטני מדי. באופן כללי היינו רוצים שרצף המספרים יהיה לכל מטרה מעשית כמו רצף מספרים אקראי אמיתי. הנה רצף של ספרות (הקסדצימליות) אקראיות1 שקיבלתי מהמחשב שלי: 4de1 a457 d1ac f25c de18 22a3 6e41 69f0 הספרה 2 חזרה על עצמה. ואני מניח שאיך בכך פסול.מה הבעיה בכך שמספר חוזר על עצמו? 1 לצורך העניין השתמשתי ב־/dev/random שהוא דרך לקבל ביטים אקראיים מ"מאגר האנטרופיה" של המערכת. ביטים (מספיק) אקראיים אפשר לקבל ממקורות כמו זמני הגישה לדיסק ותזמוני הקלדות המקלדת. |
|
||||
|
||||
יותר מכך - פלט שבו אין לפעמים חזרה על אותה ספרה הוא בבירור לא אקראי. בכלל, בפלט אקראי סביר לצפות לפעמים אפילו לחזרות ארוכות. או בקיצור: תגובה 522196. |
|
||||
|
||||
אחת החולשות שעזרו לפצח את האניגמה... |
|
||||
|
||||
מה דעתך על: 1 2 3 4 5 6 7 ... יותר יעיל, לא? |
|
||||
|
||||
1 0 1 0 1 0 ... יכול להיות יעיל אפילו יותר, ומקיים את דרישה 3 אפילו למקרה הבינארי! |
חזרה לעמוד הראשי | המאמר המלא |
מערכת האייל הקורא אינה אחראית לתוכן תגובות שנכתבו בידי קוראים | |
RSS מאמרים | כתבו למערכת | אודות האתר | טרם התעדכנת | ארכיון | חיפוש | עזרה | תנאי שימוש | © כל הזכויות שמורות |