در قسمت سیزدهم از آموزش آردوینو به بررسی مقایسه کاراکترها و مقادیر عددی، مقایسه استرینگها و همچنین، انجام مقایسههای منطقی (Logical Comparisons)، پرداختیم. در این قسمت قصد داریم درباره عملیات های محاسباتی از جمله جمع، تفریق، ضرب و تقسیم و همچنین، افزایش و کاهش مقادیر متغیرها، یافتن باقیمانده حاصل از تقسیم دو مقدار، تعیین قدرمطلق یک عدد و یافتن حداقل یا حداکثر مقادیر صحبت کنیم.
رعایت ترتیب انجام عملیات ها
برای انجام عملیات های محاسباتی روی مقادیر اسکچ خود، شما باید ترتیب انجام عملیات ها را رعایت کنید و همچنین، بتوانید متغیرهای مختلفی را کنترل کنید.
دراینخصوص، از کد زیر استفاده کنید:
1 2 3 4 5 | int myValue; myValue = 1 + 2; // addition myValue = 3 - 2; // subtraction myValue = 3 * 2; // multiplication myValue = 3 / 2; // division (the result is 1) |
در این مثال، تقسیم عدد صحیح، بخش کسری را از نتیجه تقسیم حذف میکند. بهعبارتدیگر، اگر شما دو عدد را تقسیم کنید و نتیجه تقسیم یک عدد صحیح باشد، بخش کسری از نتیجه حذف میشود. به مثال زیر توجه کنید:
1 | int value = 1 + 2 * 3 + 4;s |
در اینجا precedence (ترتیب) هر عملگر، مشخص است. بهطورکلی، عملیات های ضرب و تقسیم به عملیات های جمع و تفریق اولویت دارند؛ بنابراین نتیجه مثال ذکر شده، 11 خواهد شد. توصیه میشود که در نوشتن کد، از پرانتز استفاده کنید تا اولویت انجام محاسبات، مشخص شود.
مقدار عبارت int = 1 + (2 * 3) + 4; نیز 11 می شود؛ اما خواندن آن نسبت به عبارت int value = 1 + 2 * 3 + 4; آسان تر است؛ زیرا در آن از پرانتز استفاده شده است.
همچنین، اگر نیاز به تغییر اولویت دارید، مانند مثال زیر، میتوانید از پرانتز استفاده کنید:
1 | int value = ((1 + 2) * 3) + 4; |
در این مثال، نتیجه، 13 خواهد شد. ابتدا عبارت داخل پرانتز محاسبه می شود، یعنی ابتدا 1 به 2 اضافه می شود، سپس در 3 ضرب می شود و در نهایت به 4 اضافه می شود و مقدار نهایی 13 به دست می آید.
✅نکته
کد زیر را در نظر بگیرید:
1 2 | // 60 seconds in a minute, 60 minutes in an hour, 24 hours in a day long seconds_per_day = 60 * 60 * 24; |
مقدار این عبارت 86,400 خواهد شد که میتواند در دیتابیس long قرار گیرد. اما مقداری که واقعاً در seconds_per_day ذخیره میشود، 20,864 است. 86,400 برای دو بار اورفلو (سرریز) کردن یک عدد صحیح (integer) کافی است (86,400 – 32,768 * 2 = 20,864). این سرریز به این دلیل اتفاق می افتد که کامپایلر C نرم افزار Arduino IDE فقط یک عبارت متشکل از اعداد صحیح را می بیند. بنابراین شما باید به کامپایلر بگویید که کل عبارت را مانند یک long در نظر بگیرد، با اضافه کردن L به اولین مقدار، عبارت به صورت زیر میشود:
1 | long seconds_per_day = 60L * 60 * 24; |
اگر شما در نوشتن کد خود از پرانتز استفاده میکنید، به یاد داشته باشید که ابتدا پرانتزهای داخل عبارت محاسبه میشوند.
1 | long seconds_per_day_plus_one = 1L + 60 * (60 * 24); |
این کد بهدرستی اجرا خواهد شد:
1 | long seconds_per_day_plus_one = 1 + 60 * (60L * 24); |
افزایش و کاهش مقادیر متغیرها
برای افزایش و کاهش مقادیر متغیرها، از کد زیر استفاده کنید:
1 2 3 4 5 6 7 | int myValue = 0; myValue = myValue + 1; // this adds one to the variable myValue myValue += 1; // this does the same as the above myValue = myValue - 1; // this subtracts one from the variable myValue myValue -= 1; // this does the same as the above myValue = myValue + 5; // this adds five to the variable myValue myValue += 5; // this does the same as the above |
افزایش و کاهش مقادیر متغیرها یکی از رایجترین تسکها در برنامهنویسی است که آردوینو دارای عملگرهایی است که این کار را آسان میکند. افزایش یک مقدار، incrementing و کاهش آن، decrementing نامیده میشود. یک روشی که برای انجام این کار وجود دارد، به شرح زیر است:
1 | myValue = myValue + 1; // this adds one to the variable myValue |
همچنین، شما میتوانید عملگرهای افزایش (increment) و کاهش (decrement) را با عملگر assign ترکیب کنید، مانند مثال زیر:
1 | myValue += 1; // this does the same as the above |
اگر میخواهید مقداری را ۱ واحد افزایش یا کاهش دهید، میتوانید از عملگرهای اختصاری افزایش (increment) و کاهش (decrement) ++ یا — استفاده کنید:
1 | myValue++; // this does the same as the above |
هنگامی که عملگرهای افزایش یا کاهش بعد از یک متغیر ظاهر میشوند، این عملگرها بهعنوان عملگرهای post-increment یا post-decrement شناخته میشوند؛ زیرا آنها عملیات خود را بعد از ارزیابی متغیر انجام میدهند. همچنین، اگر آنها قبل از identifier (pre-increment or pre-decrement) ظاهر شوند، مقدار را قبل از ارزیابی متغیر، تغییر میدهند:
1 2 3 4 5 | int myVal = 1; Serial.println(myVal++); // prints 1 Serial.println(myVal); // prints 2 Serial.println(++myVal); // prints 3 Serial.println(myVal); // prints 3 |
یافتن باقیمانده حاصل از تقسیم دو مقدار
اگر میخواهید بعد از تقسیم دو مقدار صحیح، باقیمانده را پیدا کنید، از نماد % (عملگر مدول (modulus)) برای بهدستآوردن باقیمانده استفاده کنید:
1 2 | int myValue0 = 20 % 10; // get the modulus(remainder) of 20 divided by 10 int myValue1 = 21 % 10; // get the modulus(remainder) of 21 divided by 10 |
myValue0 برابر است با 0 (20 تقسیم بر 10، باقی مانده 0 دارد). myValue1 برابر است با 1 (21 تقسیم بر 10، باقی مانده 1 دارد).
بهطورکلی، عملگر مدول (modulus) بسیار مفید است، بهخصوص زمانی که میخواهید بفهمید که یک مقدار مضربی از یک عدد هست یا خیر یا بهعبارتدیگر، یک مقدار بر یک عدد مشخص، بخشپذیر هست یا نه. بهعنوانمثال، به کد زیر توجه کنید:
1 2 3 4 5 6 7 | for (int myValue = 0; myValue <= 100; myValue += 5) { if (myValue % 10 == 0) { Serial.println("The value is a multiple of 10"); } } |
در کد قبلی، عملگر مدول (modulus) روی متغیر myValue اعمال شده است. این عملگر، باقیماندهی تقسیم myValue بر ۱۰ را محاسبه میکند؛ اگر نتیجه (باقیمانده) صفر باشد، به این معنی است که myValue بر ۱۰ بخشپذیر است؛ در غیر این صورت، myValue بر ۱۰ بخشپذیر نیست.
یک مثال دیگر نیز وجود دارد. شما میتوانید از عملگر modulus برای تشخیص اعداد زوج و فرد استفاده کنید. به این صورت که اگر عددی را بر ۲ تقسیم کنید و باقیمانده برابر با صفر باشد، به این معنی است که آن عدد زوج است. در غیر این صورت، عدد فرد است.
در اینجا یک مثال مشابه نیز وجود دارد؛ اینکه شما میتوانید با استفاده از 2 و عملگر modulus، برای بررسی فرد یا زوج بودن یک مقدار استفاده کرد:
1 2 3 4 5 6 7 8 9 10 11 | for (int myValue = 0; myValue <= 10; myValue++) { if (myValue % 2 == 0) { Serial.println("The value is even"); } else { Serial.println("The value is odd"); } } |
مثال زیر، کلاک را در یک 24 ساعت برای تعداد معینی کلاک افست (offset) محاسبه می کند:
1 2 3 4 | void printOffsetHour( int hourNow, int offsetHours) { Serial.println((hourNow + offsetHours) % 24); } |
تعیین قدرمطلق یک عدد
abs(x) مقدار قدرمطلق x را محاسبه میکند. مثال زیر قدرمطلق تفاوت بین خواندن دو پورت ورودی آنالوگ را نشان میدهد:
1 2 3 4 5 6 | int x = analogRead(A0); int y = analogRead(A1); if (abs(x-y) > 10) { Serial.println("The analog values differ by more than 10"); } |
abs (x y); مقدار قدرمطلق تفاوت بین x و y را محاسبه میکند و برای مقادیر صحیح (و عدد صحیح long) استفاده میشود.
یافتن حداقل یا حداکثر مقادیر
min(x,y) کمترین مقدار و max(x,y) بیشترین مقدار را از بین دو عدد x و y برمیگرداند:
1 2 3 4 5 | int myValue = analogRead(A0); int myMinValue = min(myValue, 200); // myMinValue will be the smaller of // myVal or 200 int myMaxValue = max(myValue, 100); // myMaxValue will be the larger of // myVal or 100 |
جدول ۱ چند نمونه از مقادیر خروجی از یک تابع min با مقدار 200 را نشان می دهد. این جدول نشان می دهد که خروجی با ورودی (myValue) یکسان است، تا زمانی که مقدار از 200 بیش تر نشود.
min(myValue, 200) | myValue (مقدار ورودی) |
---|---|
99 | 99 |
100 | 100 |
150 | 150 |
200 | 200 |
200 | 201 |
جدول ۱: خروجی تابع min (با مقدار 200)
جدول ۲ خروجی تابع max با مقدار 100 را نشان می دهد. این جدول نشان می دهد تا زمانی که مقدار بیش تر یا مساوی 100 باشد، خروجی با ورودی (myValue) برابر است:
max(myValue, 100) | myValue (مقدار ورودی) |
---|---|
100 | 99 |
100 | 100 |
150 | 150 |
200 | 200 |
201 | 201 |
جدول ۲: خروجی تابع max (با مقدار 100)
استفاده از تابع min برای محدودکردن حد بالا (upper bound) میتواند در انتخاب مقدار کمتر کمک کند. این کار ممکن است در ابتدا کمی متفاوت به نظر برسد، اما با بازگرداندن کوچکترین مقدار بین ورودی و مقدار حداقل، خروجی تابع min هرگز از مقدار حداقل، بیشتر نخواهد بود (در مثال قبل، مقدار 200).
به طور مشابه، از تابع max برای محدودکردن حد پایین (lower bound) استفاده میشود. خروجی تابع max هرگز کمتر از مقدار ماکزیمم یا همان حداکثر (در مثال قبل، مقدار 100) نمی باشد.
اگر میخواهید از توابع min یا max برای بیش از دو مقدار استفاده کنید، میتوانید مقادیر را بهصورت زیر بنویسید:
1 2 | / myMinValue will be the smaller of the three analog readings: int myMinValue = min(analogRead(0), min(analogRead(1), analogRead(2))); |
در این مثال، ابتدا مقدار حداقل (مینیمم) پورتهای آنالوگ 1 و 2 و سپس مقدار حداقل آن با پورت 0 محاسبه میشود. این روش میتواند برای تعداد دلخواهی از مقادیر تکرار شود، اما توجه داشته باشید که پرانتزها را به درستی قرار دهید. مثال زیر ماکزیمم (حداکثر) چهار مقدار را محاسبه می کند:
1 2 3 | int myMaxValue = max(analogRead(0), max(analogRead(1), max(analogRead(2), analogRead(3)))); |