عد

عدد صحیح در Rust

1 تمرین

درباره‌ی عدد صحیح

عدد صحیح، عددی کامل است. هیچ بخش کسری یا اعشاری ندارد. اعداد صحیح در ماشین به صورت الگویی از بیت‌های باینری نمایش داده می‌شوند.

عدد صحیح ممکن است علامت‌دار باشد یا نباشد. علامت‌دار بودن یعنی یکی از بیت‌های عدد را کنار بگذاریم تا نشان دهد آن عدد منفی است یا نه.

همه‌ی اعداد صحیح یک عرض بیت دارند، که همان تعداد بیت‌های تشکیل‌دهنده‌ی آن عدد است. این موضوع بر بیشترین مقداری که آن نوع عدد صحیح می‌تواند نمایش دهد تأثیر می‌گذارد.

برای مثال، یکی از رایج‌ترین انواع عدد صحیح u8 است: یک عدد صحیح ۸ بیتی بدون علامت. ممکن است این نوع را به عنوان یک بایت بشناسید. کمترین مقدار آن ۰ و بیشترین مقدارش ۲۵۵ است.

Rust دوازده نوع عدد صحیح ابتدایی دارد که بر اساس عرض بیت و علامت‌دار بودن تفکیک شده‌اند:

بدون علامت علامت‌دار
u8 i8
u16 i16
u32 i32
u64 i64
u128 i128
usize isize

عرض بیت یک عدد صحیح همیشه با عددی که بعد از u یا i می‌آید مشخص می‌شود. usize و isize ویژه‌اند: عرضشان با عرض یک اشاره‌گر روی ماشین هدف یکسان است. یعنی روی معماری ۶۴ بیتی، usize و isize عرض ۶۴ بیت دارند، اما روی معماری ۳۲ بیتی، عرضشان ۳۲ بیت است.

کدام را استفاده کنم؟

به‌طور کلی، اگر فقط می‌خواهید عددی را نمایش دهید، از i32 استفاده کنید: ۳۲ بیت بازه‌ی به‌قدر کافی گسترده‌ای دارد که سرریز شدن نسبتاً بعید باشد، و اعداد علامت‌دار شگفتی‌های کمتری از اعداد بدون علامت دارند. i32 معادل long در C یا int در Java است. اگر از یک مقدار عددی استفاده کنید و نوع را به‌صراحت مشخص نکنید، به صورت پیش‌فرض i32 در نظر گرفته می‌شود.

اگر با داده‌های باینری کار می‌کنید، ساده‌ترین راه کار کردن با بایت‌هاست: &[u8] یا Vec<u8>.

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

اگر داده‌هایتان در یک عدد صحیح ۳۲ بیتی جا نمی‌گیرد، به فکر گسترش آن به یک عدد صحیح ۶۴ یا ۱۲۸ بیتی باشید. اگر داده‌هایتان در یک عدد صحیح ۱۲۸ بیتی جا نمی‌گیرد، می‌توانید از یک نوع عدد صحیح بزرگ استفاده کنید، مانند آنچه num-bigint فراهم می‌کند.

اعداد صحیح ۱۶ بیتی چندان رایج نیستند، اما اگر هدف‌تان میکروکنترلرهای خاصی باشد، می‌توانند مفید باشند.

اگر می‌دانید که برای برنامه‌تان هیچ حالت منفی معتبری وجود ندارد، بهتر است به جای یک عدد صحیح علامت‌دار از یک عدد صحیح بدون علامت استفاده کنید. شمارش مثال خوبی برای این است.

تبدیل بین اعداد صحیح

Rust هیچ تبدیل عددی ضمنی ندارد. اگر لازم است بین انواع عدد صحیح تبدیل انجام دهید، دو راهبرد اساسی وجود دارد: کلیدواژه‌ی as و traitهای From و TryFrom.

استفاده از کلیدواژه‌ی as ساده است: expr as Type. اما نکات و ظرافت‌های متعددی وجود دارد که هنگام استفاده از تبدیل‌های as باید در نظر داشته باشید.

تبدیل نوع مبتنی بر trait کمی پیچیده‌تر است، اما ایمن‌تر: traitهای تبدیل فقط جایی پیاده‌سازی می‌شوند که ایمن باشند. برای مثال، i32 From<u8>، From<u16>، From<i8> و From<i16> را پیاده‌سازی می‌کند: هر مقداری که با هر یک از این انواع قابل نمایش باشد، تضمین می‌شود که در i32 هم قابل نمایش است. می‌توان از آن به شکل i32::from(expr) یا expr.into() استفاده کرد، که در آن expr یکی از آن انواع است. i32 همچنین TryFrom<u32>، TryFrom<u64>، TryFrom<u128>، TryFrom<usize>، TryFrom<i64>، TryFrom<i128> و TryFrom<isize> را پیاده‌سازی می‌کند. این تبدیل‌ها بسته به مقدار، یا به‌صراحت موفق می‌شوند یا سرریز می‌کنند. برای استفاده از این‌ها، باید traitهای std::convert::TryFrom یا std::convert::TryInto را به تناسب import کنید و سپس از i32::try_from(expr) یا expr.try_into() استفاده کنید، که در آن expr نوع مناسبی است.

استفاده از تبدیل نوع مبتنی بر trait به جای تبدیل با as عموماً ترجیح داده می‌شود، به‌ویژه هنگام تبدیل از یک نوع پهن‌تر به یک نوع باریک‌تر. تبدیل نوع مبتنی بر trait به شکلی ناچیز گران‌تر از تبدیل با as است: استفاده از as به دلایل کارایی ارزشش را ندارد، مگر در یک حلقه‌ی بسیار داغ.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود