درس ۳ از ۴۹ · آغاز راه

گونه‌ها

سلام زبانی ایستا است: گونه‌ی هر مقدار پیش از اجرا مشخص است و مترجم نمی‌گذارد گونه‌های ناسازگار با هم قاطی شوند.

گونه‌های پایه

types-basic.salam
تابع ریشه:
    عدد := ۴۲
    اعشاری := ۳.۱۴
    متن := "سلام"
    درستی := نادرست
    حرف := u'س'
    سرچاپ عدد, اعشاری, متن, درستی, حرف
پایان
خروجی42 3.14 سلام false س
گونهانگلیسیکاربرد
صحیحintعدد صحیح ۳۲ بیتی
صحیح۸، صحیح۱۶، صحیح۶۴، صحیح۱۲۸i8، i16، i64، i128عدد صحیح با اندازه‌ی مشخص
طبیعی، طبیعی۸ تا طبیعی۱۲۸uint، u8 تا u128عدد صحیح بدون علامت
اعشار۶۴، اعشار۳۲f64، f32عدد اعشاری
منطقیboolدرست یا نادرست
رشتهstrمتن (یونیکد)
نویسهcharیک نویسه، مثل u'س'
اندازه مثبت، اندازهusize، sizeعدد هم‌اندازه‌ی نشانی حافظه

متن درس جداگانه‌ای دارد: رشته‌ها و متن. این درس درباره‌ی عددها، مقدارهای منطقی و نویسه‌هاست و این‌که چطور مقداری را از یک گونه به گونه‌ی دیگر ببریم.

اندازه و مبنای اعداد

عددها را می‌توانید در مبنای شانزده (0xFF)، دو (0b1010) و هشت (0o17) هم بنویسید و برای خوانایی رقم‌ها را با _ جدا کنید.

types-ints.salam
تابع ریشه:
    کوچک := ۱۲۰ برگردان صحیح۸
    بزرگ := ۹_۰۰۰_۰۰۰_۰۰۰ برگردان صحیح۶۴
    مثبت := ۴۰۰۰۰۰۰۰۰۰ برگردان طبیعی
    سرچاپ کوچک, بزرگ, مثبت
    سرچاپ 0xFF, 0b1010, 0o17
پایان
خروجی120 9000000000 4000000000 255 10 15

عدد صحیحی که در کد می‌نویسید صحیح است، مگر آن‌که در آن جا نشود: ۹۰۰۰۰۰۰۰۰۰ خودبه‌خود صحیح۶۴ می‌شود. اندازه‌گونه اندازه‌ی هر گونه را بر حسب بایت می‌دهد:

types-sizeof.salam
ساختار نقطه:
    ایکس: صحیح
    ایگرگ: صحیح
پایان

تابع ریشه:
    سرچاپ "صحیح۸:", اندازه‌گونه(صحیح۸)
    سرچاپ "صحیح:", اندازه‌گونه(صحیح)
    سرچاپ "صحیح۶۴:", اندازه‌گونه(صحیح۶۴)
    سرچاپ "اعشار۶۴:", اندازه‌گونه(اعشار۶۴)
    سرچاپ "نقطه:", اندازه‌گونه(نقطه)
پایان
خروجیصحیح۸: 1 صحیح: 4 صحیح۶۴: 8 اعشار۶۴: 8 نقطه: 8

بازه‌ی صحیح از حدود منفی دو میلیارد تا مثبت دو میلیارد است و صحیح۶۴ تا حدود نه میلیارد میلیارد می‌رود و صحیح۱۲۸ تا حدود ۱٫۷ ضرب در ده به توان ۳۸. طبیعی۸ عددهای ۰ تا ۲۵۵ را نگه می‌دارد، یعنی درست یک بایت.

وقتی عدد جا نمی‌شود

اگر نتیجه‌ی محاسبه از مرز گونه‌اش بگذرد، عدد از سر دیگر بازه سر درمی‌آورد و برنامه بی‌هیچ پیامی ادامه می‌دهد؛ به این پدیده سرریز می‌گویند. اگر کامپایلر مقدارها را ببیند، مثل بازدید += ۱۰۰۰ درست پس از یک عدد بزرگ ثابت، ساخت را متوقف می‌کند؛ برای همین این مثال آن‌ها را از یک تابع می‌گذراند. شمارنده‌ی بازدیدی که در صحیح نگه داشته شود پس از حدود دو میلیارد بازدید منفی می‌شود، اما همان شمارنده با صحیح۶۴ درست ادامه می‌دهد. گونه‌های بدون علامت در صفر سرریز می‌کنند، پس ۳ منهای ۵ عددی مثبت و بسیار بزرگ می‌شود.

types-overflow.salam
تابع افزودن بازدید(بازدید: صحیح، تازه: صحیح): صحیح:
    برگشت بازدید + تازه
پایان

تابع ریشه:
    سرچاپ "بازدید با صحیح:"، افزودن بازدید(۲۱۴۷۴۸۳۰۰۰، ۱۰۰۰)
    ناپایا کل بازدید := ۲۱۴۷۴۸۳۰۰۰ برگردان صحیح۶۴
    کل بازدید += ۱۰۰۰
    سرچاپ "بازدید با صحیح۶۴:"، کل بازدید
    موجودی := ۳ برگردان طبیعی
    فروش := ۵ برگردان طبیعی
    سرچاپ "موجودی باقی‌مانده:"، موجودی - فروش
پایان
خروجیبازدید با صحیح: -2147483296 بازدید با صحیح۶۴: 2147484000 موجودی باقی‌مانده: 4294967294

پس گونه را از روی بزرگ‌ترین مقداری که انتظارش را دارید انتخاب کنید، نه نخستین مقداری که می‌بینید. برای شمارنده‌ها، اندازه‌ی پرونده‌ها، مبلغ به ریال و زمان به میلی‌ثانیه صحیح۶۴ بنویسید و گونه‌های بدون علامت را برای چیزهایی نگه دارید که واقعاً هرگز منفی نمی‌شوند، مثل بایت‌ها.

عددهای اعشاری

عدد اعشاری مثل ۲.۵ از گونه‌ی اعشار۶۴ است و می‌توان آن را با توان ده نوشت: 1.5e3 یعنی ۱۵۰۰. جداکننده‌ی اعشار همیشه نقطه است و ٫ پذیرفته نمی‌شود. هنگام چاپ کوتاه‌ترین شکلی نوشته می‌شود که دوباره همان عدد خوانده شود، پس ۱۰.۰ به شکل 10 چاپ می‌شود. عددهای اعشاری در مبنای دو نگه داشته می‌شوند و بیشتر کسرهای ده‌دهی در مبنای دو شکل دقیقی ندارند:

types-float.salam
تابع ریشه:
    سرچاپ ۰.۱ + ۰.۲
    سرچاپ ۰.۱ + ۰.۲ == ۰.۳
    سرچاپ ۱۰.۰، ۲.۵۰، 1.5e3، 2.5e-2
    قیمت := ۱۹.۹۹
    سرچاپ قیمت * ۳
    سرچاپ ۰.۱ برگردان اعشار
پایان
خروجی0.30000000000000004 false 10 2.5 1500 0.025 59.97 0.10000000149011612

به همین خطای کوچک است که نتیجه‌های اعشاری را نباید با == مقایسه کرد؛ به‌جایش بررسی کنید که اختلافشان به‌اندازه‌ی کافی کوچک باشد. اعشار (همان اعشار۳۲) حافظه‌ی کمتری می‌گیرد اما فقط حدود هفت رقم را درست نگه می‌دارد، همان‌طور که خط آخر نشان می‌دهد. برای پول، که هر ریالش باید جور دربیاید، از کتابخانه‌ی اعشاری استفاده کنید یا مبلغ را به ریال در یک صحیح۶۴ بشمارید.

منطقی و نویسه

مقدار منطقی یا درست است یا نادرست و هر شرطی در سلام باید از همین گونه باشد. عدد به‌جای شرط پذیرفته نمی‌شود: اگر تعداد: خطا می‌دهد (شرط 'اگر' باید بولی باشد، اما 'صحیح' دریافت شد)؛ بنویسید اگر تعداد != ۰:.

نویسه یک نویسه را نگه می‌دارد. 'A' فقط برای یک بایت کار می‌کند، یعنی حرف یا رقم انگلیسی؛ هر حرف دیگری، از جمله همه‌ی حرف‌های فارسی، پیشوند u می‌خواهد، مثل u'س'، و اگر فراموشش کنید مترجم یادآوری می‌کند. تبدیل نویسه به صحیح کد یونیکد آن را می‌دهد و برعکسش هم ممکن است:

types-char.salam
تابع ریشه:
    حرف := 'A'
    سرچاپ حرف، حرف برگردان صحیح
    بعدی := (حرف برگردان صحیح + ۱) برگردان نویسه
    سرچاپ بعدی
    سین := u'س'
    سرچاپ سین، سین برگردان صحیح
    آماده := درست
    سرچاپ آماده، وارونه آماده
پایان
خروجیA 65 B س 1587 true false

ترکیب گونه‌ها و تبدیل

در محاسبه، اگر چیزی از دست نرود، مقدار خودبه‌خود به گونه‌ی بزرگ‌تر می‌رود: صحیح با اعشار۶۴ نتیجه‌ی اعشار۶۴ می‌دهد و صحیح با صحیح۶۴ نتیجه‌ی صحیح۶۴. اما برعکسش هرگز بی‌صدا انجام نمی‌شود: گذاشتن اعشار۶۴ در متغیری از گونه‌ی صحیح، یا فرستادن صحیح۶۴ به پارامتری از گونه‌ی صحیح، خطاست تا وقتی که تبدیل را با برگردان صریح بنویسید.

types-mix.salam
تابع ریشه:
    تعداد := ۳
    جمع := ۵۹.۹۷
    میانگین := جمع / تعداد
    سرچاپ "میانگین قیمت:"، میانگین
    سرچاپ "گردشده به پایین:"، میانگین برگردان صحیح
    جمعیت := ۸۱۰۰۰۰۰۰۰۰
    سرچاپ "یک نفر بیشتر:"، جمعیت + ۱
پایان
خروجیمیانگین قیمت: 19.99 گردشده به پایین: 19 یک نفر بیشتر: 8100000001

تقسیم دو عدد صحیح، صحیح است و بخش اعشاری کنار گذاشته می‌شود. اگر بخش اعشاری را می‌خواهید، پیش از تقسیم یکی از دو طرف را تبدیل کنید:

types-cast.salam
تابع ریشه:
    سرچاپ ۷ / ۲
    سرچاپ ۷ % ۲
    سرچاپ (۷ برگردان اعشار۶۴) / ۲.۰
    عدد := ۳.۹
    سرچاپ عدد برگردان صحیح
    سرچاپ "۴۲".به صحیح() + ۸
پایان
خروجی3 1 3.5 3 50

قاعده‌های برگردان به‌طور خلاصه:

  • تبدیل اعشاری به صحیح بخش اعشاری را به سمت صفر می‌بُرد: ۳.۹ برگردان صحیح می‌شود ۳ و -۷.۹ برگردان صحیح می‌شود -7. گرد نمی‌کند.
  • عدد صحیحی که در گونه‌ی مقصد جا نشود سرریز می‌کند: ۳۰۰ برگردان طبیعی۸ می‌شود ۴۴.
  • تبدیل به گونه‌ای که مقدار از قبل دارد خطاست (E093، تبدیل بی‌فایده)؛ آن را بردارید.
  • متن با برگردان عدد نمی‌شود: "۴۲" برگردان صحیح خطاست. از به صحیح() استفاده کنید که در ادامه آمده است.

متن و عدد

عددها خیلی وقت‌ها به شکل متن می‌رسند: کاربر تایپشان می‌کند، از پرونده خوانده می‌شوند یا از یک فرم وب می‌آیند. به صحیح() و به اعشار() متن را به عدد تبدیل می‌کنند و رقم‌های فارسی را هم می‌شناسند. + با رشته‌ای در سمت چپ، عدد را به متن تبدیل می‌کند.

types-parse.salam
واردسازی رشته

تابع ریشه:
    تعداد := "۱۲".به صحیح()
    وزن := "۲.۵".به اعشار()
    نادرست‌نوشته := "دوازده".به صحیح()
    سرچاپ تعداد * ۲، وزن * ۲.۰، نادرست‌نوشته
    برچسب := "تعداد: " + تعداد
    سرچاپ برچسب
    سرچاپ "وزن کل: " + وزن * تعداد
    سرچاپ رشته.به رقم فارسی(برچسب)
پایان
خروجی24 5 0 تعداد: 12 وزن کل: 30 تعداد: ۱۲

به مقدار سوم دقت کنید: متنی که عدد نیست صفر می‌دهد و خطایی هم در کار نیست. اگر صفر مقداری است که واقعاً ممکن است پیش بیاید، اول خود متن را بررسی کنید، برای نمونه با تابع‌های تشخیص رقم در کتابخانه‌ی رشته. عددها همیشه با رقم انگلیسی چاپ می‌شوند؛ خط آخر نشان می‌دهد که رشته.به رقم فارسی چطور متنی آماده را با رقم فارسی برمی‌گرداند. برای نوشتن عدد اعشاری با تعداد رقم مشخص پس از ممیز، از تبدیل.قالب اعشار با دقت در کتابخانه‌ی تبدیل استفاده کنید.

نام تازه برای گونه‌های موجود (گونه سن = صحیح) و گونه‌های کاملاً تازه‌ای که روی آن‌ها ساخته می‌شوند در درس گونه‌های تازه آمده‌اند.