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

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

10/10/2019

אנשים פעם מאוד אהבו להכניס קבועים בכל מיני בסיסי ספירה לקוד התוכניות שלהם ולכן מתכנני שפות תכנות הכניסו תמיכה בכל מיני כתיבים שהיום עשויים להיראות קצת מוזרים. הבסיסים הפופולריים היו בסיס בינארי (בסיס 2), בסיס אוקטלי (בסיס 8) ובסיס הקסדצימלי (בסיס 16), וכמובן הבסיס הדצימלי הרגיל (בסיס 10).

כך קוד ה Python2 הבא עשוי להפתיע מתכנתי פייתון מודרניים:

x = 0b10
print(x) # prints 2

x = 011
print(x) # prints 9

x = 0x10
print(x) # prints 16

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

התנהגות זו היא שהובילה לבאג מעניין בקוד שלי שמזהה האם יום מסוים הוא חג. הקוד כתוב ב Bash ושימו לב לשורה הבאה:

if (( $(date +%"H") < 20 ))

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

-bash: ((: 08: value too great for base (error token is "08")

וזה ברור: המספר 08 הוא לא מספר תקין בבסיס אוקטלי ולכן Bash לא יודע להגיד או הוא קטן או גדול מ-20. אחרי שהבנו את הבעיה ברור גם הפיתרון - נדפיס את השעה בלי ריפוד באפסים וכך התנאי שנקבל יהיה 8 < 20, איתו לאף אחד אין בעיה. ב Bash זה אומר ששורת הבדיקה תהיה:

if (( $(date +%"_H") < 20 ))

והלקח? במחשבים, שלא כמו בחשבון, האפס בהתחלה עלול לעשות נזק גדול.