Rust/פעולות אריתמטיות
Rust |
---|
|
בשיעור זה נלמד על פעולות החשבון הבסיסיות בשפת ראסט. בניגוד לשפות אחרות שמאפשרות באופן מובנה שימוש בפעולות אריתמטיות רבות, שפת ראסט היא שפה מצומצמת ולכן היא כוללת רק את פעולות החשבון הבסיסיות ביותר (כמו חיבור או כפל). פעולות מתקדמות יותר, כמו חזקה, שורש ופעילות טריגונומטריות, אינן חלק מהשפה אלא שייכות לספריות שלה, אשר בהן ניגע בהמשך.
הפעולות הבסיסיות
עריכהשפת ראסט מאפשרת לחבר (ע"י +), לחסר (ע"י -), להכפיל (ע"י *), לחלק (ע"י /), ולמצוא שארית (ע"י % - מודולו). בדומה לסימן פעולת ההשמה ('='), גם סימני פעולות החשבון מכונים אופרטורים. להלן מספר דוגמאות:
let x = 4;
let y = 2;
// Prints 4 + 2 = 6
println!("{} + {} = {}\n", x, y, x + y);
// Prints 4 - 2 = 2
println!("{} - {} = {}\n", x, y, x - y);
// Prints 4 * 2 = 8
println!("{} * {} = {}\n", x, y, x * y);
// Prints 4 / 2 = 2
println!("{} / {} = {}\n", x, y, x / y);
// Prints 4 % 2 = 0
println!("{} % {} = {}\n", x, y, x % y);
אפשר לבצע פעולות אריתמטיות על מספרים, משתנים, או כל שילוב של משתנים ומספרים:
let x = 2;
let y = 3;
// Prints 13
println!("{}\n", x + y + 3 + 5);
שימו לב שניתן לבצע פעולות אריתמטיות גם על משתנים מסוג immutable. הסיבה לכך היא שכשאנחנו מבצעים פעולה אריתמטית, אין אנו באים לשנות בהכרח את ערכו של המשתנה ולשמור בו את התוצאה של הביטוי בו. לכן, אין כל מניעה להשתמש בערך של משתנים מסוג immutable.
סדר פעולות החשבון
עריכהסדר פעולות החשבון בשפת ראסט הוא המקובל באלגברה בסיסית, ולכן כפל (*), לדוגמה, מבוצע לפני חיבור (+). השורה הבאה, לדוגמה, תדפיס 17:
println!("{}\n", 2 + 3 * 5);
בדיוק כבאלגברה בסיסית, ניתן להשתמש בסוגריים כדי לציין סדר פעולות שונה. השורה הבאה, לדוגמה, תדפיס 25:
println!("{}\n", (2 + 3) * 5);
השמת ערכים
עריכההשמה ואתחול
עריכהכפי שראינו בפרק על משתנים, ניתן להשתמש בסימן '=' להשמה ואתחול של משתנים.
let x = 7;
let y = x + 3;
חשוב להבין מה קורה כאן בשורה השנייה. מאחר שהמשתנה x הוגדר לפני המשתנה y, ניתן להשתמש בערכו של x על מנת להגדיר את y. ראשית מחשבים את הביטוי x + 3 (ערכו כאן 10) ואז משימים ערך זה למשתנה y. אפשר גם להשים למשתנה ערך חדש שתלוי בערכו הקודם במידה והגדרנו את המשתנה בתור mutable. נתבונן בדוגמה הבאה:
let mut x = 5;
x = x + 2;
הכוונה איננה למשוואה אלגברית על x (שאגב, נטולת פתרון). הכוונה היא לחשב את ערכו של הביטוי x + 2 (במקרה זה, 4), ולהשים ערך זה חזרה למשתנה x, דבר שידרוס את הערך הקודם המצוי ב-x (במקרה זה, 2).
סימני קיצור בהשמה עצמית
עריכהx = x + 2;
נתבונן בדוגמה למעלה. בהנחה ש-x הוא mutable, הקוד יבצע השמה עצמית של x לערכו הקודם ועוד 2. בפועל, צורת השמה של הגדלה עצמית, כמו בדגומה האחרונה, נפוצה מאוד בעת כתיבת קוד ולכן אפשר לכתוב את הביטוי הקודם גם באופן מקוצר יותר:
x += 2;
המשמעות כאן זהה לחלוטין: ממחשבים את ערכו של הביטוי x + 2, ומשימים את הערך ל-x.
שפת Rust כוללת סימונים מקוצרים להשמות עצמיות לכל חמש פעולות החשבון הבסיסיות:
// x = x + 1
x += 1;
// y = y - 3
y -= 3;
// z = z * 8
z *= 8;
// w = w / 4
w /= 4;
// p = p % 2
p %= 2;
כדאי לדעת: נוסף לקיצורים שהצגנו, בשפות תכנות רבות (ביניהן שפת C) ישנו קיצור שמגדיל או מקטין את ערך המשתנה ב-1 (למשל x++ או x--). הקיצור שימושי במיוחד לשימוש בתכונות מתקדמות יותר של שפות תכנות שטרם עסקנו בהם (כמו לולאות). אף על פי כן, בשפת ראסט אין קיצור של הגדלה או הקטנה עצמית של ערך המשתנה ב-1 ויש להשתמש בביטוי x+=1 או x-=1. |
פעולות אריתמטיות על מספרים מטיפוסים שונים
עריכהכמו שראינו בפרק הקודם, בלתי אפשרי לבצע פעולת השמה למשתנים מטיפוסים שונים ללא ביצוע הסבה. חשוב לציין שהדבר נכון גם לגבי ביצוע פעולות אריתמטיות. לא ניתן לבצע פעולות אריתמטיות בין שני משתנים שאינם מאותו טיפוס. כדי להמחיש זאת, ננסה להריץ את הדוגמה הבאה:
println!("{}\n", 3.3 + 4); // error: mismatched types
כפי שנוכל לראות, למרות שמדובר בתוכנית פשוטה המדפיסה את הסכום של 3.3 ועוד 4, הקומפיילר יחזיר לנו הודעת שגיאה. הסיבה לכך היא שהוא איננו יודע איך לחבר שני משתנים מטיפוסים שונים (במקרה זה מספר שלם ומספר עשרוני). אפשר לומר שהקומפיילר לא יודע איך להציג את התוצאה למשתמש - בתור מספר שלם או בתור מספר עשרוני (הזכירו לעצמכם מדוע מדובר בשתי תוצאות שונות). לכן, אם נרצה להדפיס את התוצאה של הביטוי, נבצע הסבה לאחד המשתנים לטיפוס התואם של המשתנה השני.
איבוד אפשרי של מידע בעת ביצוע פעולת חילוק
עריכהלעתים נרצה לבצע במהלך התוכנית חלוקה של מספר אחד במספר אחר. כפי שכבר הזכרנו, לשם ביצוע הפעולה, נשתמש באופרטור '/' (לוכסן או סלאש). יתכן שהפעולה שנבצע תותיר אחריה שארית כלשהי, ולכן התוצאה שתתקבל (המנה) תהיה מספר לא שלם. עם זאת, סביר להניח שפעולת החילוק עצמה תתבצע על משתנים מטיפוס של מספר שלם וכבר ראינו שהקומפיילר נוהג לעתים להתייחס למספרים עשרוניים כאל מספרים שלמים. נריץ למשל את הדוגמה הבאה:
println!("{}\n", (7 + 9 + 1) / 5); // prints 3
הדוגמה אמורה להדפיס את תוצאת החילוק של 17 ב-5 שהיא שוות ערך ל-3.4. עם זאת, כשנריץ את הקוד נגלה שהתוצאה שתודפס לפנינו היא המספר 3. אל דאגה! מדובר בטעות רווחת אצל מתכנתים מתחילים. הסיבה לכך שהודפס 3 היא שהקומפיילר נוהג להתייחס הן לביטוי שבמונה והן לביטוי שבמכנה כאל משתנים מטיפוס של מספר שלם ולכן, תוצאת החילוק של שני מספרים שלמים תהיה בהכרח מטיפוס מספר שלם.
לכן, אם נרצה לקבל תוצאה מדויקת של הביטוי נצטרך לבצע הסבה לשני חלקי הביטוי (המונה והמכנה) לטיפוס של מספר עשרוני. שימו לב! אם נבצע הסבה רק לחלק אחד של הביטוי, הקומפיילר עדיין יתייחס לחלק השני שלו כאל טיפוס מסוג מספר שלם ולכן נקבל שגיאת קומפילציה, שכן כפי שאמרנו מקודם, לא ניתן לבצע פעולות בין מספרים מטיפוסים שונים.
לפני שאתם ממשיכים הלאה, ודאו שאתם מבינים את ההבדלים בין הפעולות הבאות:
println!("{}\n", (7 + 9 + 1) / 5); // prints 3
println!("{}\n", (7 + 9 + 1) as f64 / 5 as f64); // prints 3.4
println!("{}\n", (7 + 9 + 1) as f64 / 5.0); // prints 3.4
println!("{}\n", (7 as f64 + 9 as f64 + 1 as f64) / 5 as f64); // prints 3.4
println!("{}\n", (7 + 9 + 1) / 5 as f64); // error: mismatched types
println!("{}\n", ((7 + 9 + 1) / 5) as f64); // prints 3
println!("{}\n", (7 + 9 + 1 as f64) / 5 as f64); // error: mismatched types
תרגול
עריכהלפני שתעברו לשיעור הבא, בשלב זה מומלץ לגשת לעמוד התרגול של השיעור. התרגילים של שיעור זה עוסקים בביצוע הפעולות הבסיסיות שהוצגו בשיעור לצד יישום הנושאים שהועברו בשיעורים הקודמים. שימו לב! שיעור זה הוא השיעור הראשון בו תתנסו בכתיבת קוד ממשי בעצמכם. בשיעורים הבאים נעסוק כבר בכתיבת קוד מסובך יותר שהבנתו כרוכה בהבנה מלאה של כל נושאי השיעור. בהצלחה!
הפרק הקודם: פלט והצללה |
פעולות אריתמטיות תרגילים |
הפרק הבא: ביטויים בוליאניים ותנאים/מתחילים |