برنامه نویسی

انواع تعداد گسترش یافته… (در RUST)

معرفی

به این مقاله که در آن می خواهیم چیزهای بیشتری در مورد انواع اعداد در Rust ببینیم، خوش آمدید. اگر ندیده اید مقاله قبلی در جایی که در مورد اصول انواع اعداد در Rust صحبت کردیم، لطفاً ابتدا آن را بررسی کنید.

توجه: این مقاله شامل نمونه هایی است که از آنها الهام گرفته شده است زنگ زدگی در عمل کتاب توسط تیم مک نامارا.

کمی در مورد من…

سلام خواننده 🖐. من چیرانجیوی تیرونگاری هستم و یک مهندس نرم افزار هستم. می توانید اطلاعات بیشتری در مورد من پیدا کنید لینکدین و توییتر. همچنین در من مشترک شوید کانال یوتیوب اگر به Rust، DevOps و به طور کلی به فناوری علاقه دارید.

حالا بیایید شروع کنیم.

مقایسه ارزش ها

ما اغلب باید چندین مقدار را با هم مقایسه کنیم و کاری را بر اساس آن در کد انجام دهیم. بررسی می کنیم که آیا یک مقدار کوچکتر، بزرگتر، مساوی یا مساوی دیگری نیست. در Rust، اگر مقادیر متعلق به یک نوع باشند، می‌توانیم آن‌ها را با هم مقایسه کنیم. این واضح است. این در اکثر زبان ها اتفاق می افتد، درست است؟ ما نمی توانیم یک عدد صحیح را با یک رشته در جاوا مقایسه کنیم. بله، اما در Rust بسیار سختگیرانه تر است. ما نمی توانیم یک نوع عدد صحیح (مانند u16) را با یک نوع عدد صحیح دیگر (مانند یک u64) مقایسه کنیم.

مثلا،

fn main() {
    let num1 = 13_u16;
    let num2 = 300_u64;

    if num1 < num2 {
        println!("Went through!");
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر بخواهید این برنامه را کامپایل کنید، با خطای “Types mismatched” مواجه می شود. اما، نمی‌توانیم به استفاده از یک نوع برای همه متغیرها ادامه دهیم. برخی از متغیرها ممکن است در مقایسه با بقیه به فضای کمتری نیاز داشته باشند. ما نمی توانیم فقط برای مقایسه از نوع بزرگتر استفاده کنیم.

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

fn main() {
    let num1 = 13_u16;
    let num2 = 300_u64;

    if (num1 as u64) < num2 {
        println!("Went through!");
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر آن را اجرا کنید، باید “Went through!” خروجی

اگر دقت کنید، ما نوع کوچک‌تر را به بزرگ‌تر تایپ کردیم، نه برعکس. این به این دلیل است که وقتی می‌خواهیم یک نوع بزرگ‌تر را به یک نوع کوچک‌تر تایپ کنیم، با مشکلات زمان اجرا مواجه می‌شویم. سعی کنید در حین چاپ یک عدد u128 بزرگتر را به نوع u8 بریزید تا آن را در عمل ببینید. تغییر در مقادیر را خواهید دید. این به این دلیل است که u8 نمی‌تواند اعداد بزرگ‌تری را که به u128 نیاز دارند را در خود جای دهد و به همین دلیل در اطراف پیچیده می‌شود.

مشکل با ممیز شناور

نقاط شناور اعدادی هستند که در پایه 10 نشان داده شده اند. اما هر چیزی که در حافظه کامپیوتر ذخیره می شود در پایه 2 ذخیره می شود. این جایی است که مشکلات ایجاد می شود. این باعث می شود که اعداد هنگام برخورد با ممیز شناور دقت خود را از دست بدهند. برنامه زیر خطایی می دهد که به طور کلی غیرمنتظره است.

fn main() {
    // assert_eq! checks if both arguments are equal
    // If not, the program panics (throws runtime error and crashes)
    assert_eq!(0.1 + 0.2, 0.3);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و خطا به شکل زیر است:

تصویر خطا

همانطور که می بینید، ارزیابی شد 0.1 + 0.2 مانند 0.30000000000000004.

در اینباره چکاری می توانیم بکنیم؟

تفاوت کوچکی که در محاسبه بالا به دست آوردیم نامیده می شود اپسیلون و می توانیم برنامه ها را به گونه ای بنویسیم که هنگام مقایسه اپسیلون نادیده گرفته شود. برنامه برای همین در زیر است.

fn main() {
    let sum: f32 = 0.1 + 0.2;
    let expected: f32 = 0.3;
    let absolute_difference = (expected - sum).abs();

    // assert! panics if the expression inside evaluates to false
    assert!(absolute_difference <= f32::EPSILON);
    // EPSILON is a constant available for both f32 and f64 types
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در این مورد نباید هیچ خطایی وجود داشته باشد زیرا ما در حال محاسبه آن هستیم اپسیلون اکنون.

یک عدد نیست

عدد نیست (که در) همچنین یک عدد ممیز شناور است که هیچ مقداری ندارد. این معمولاً زمانی حاصل می شود که ما سعی می کنیم عملیاتی را انجام دهیم که منجر به آن می شود تعریف نشده. به عنوان مثال می توان به جذر اعداد منفی و غیره اشاره کرد. برای دیدن این، اجازه دهید یک برنامه بنویسیم.

fn main() {
    let root = (-56_f32).sqrt(); // sqrt function returns the square root
    assert_eq!(root, f32::NAN);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این برنامه وحشت می کند حتی اگر هر دو استدلال برای assert_eq! هستند NAN. این بخاطر این است که NAN برابر نیست NAN. با استفاده از برنامه زیر می توانید این موضوع را تایید کنید.

fn main() {
    assert_eq!(f32::NAN, f32::NAN);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حتی این وحشت می کند که این گفته ما را تأیید می کند NAN برابر نیست NAN. چگونه می‌توانیم نتیجه را تأیید کنیم؟ NAN یا نه؟ ما یک تابع به نام داریم is_nan() به این منظور. بیایید برنامه خود را برای استفاده از آن تابع تغییر دهیم.

fn main() {
    let root = (-42.0_f32).sqrt();
    assert!(root.is_nan());
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این برنامه نباید وحشت کند. ما یک تابع به نام داریم is_infinity() برای رسیدگی به موارد بی نهایت مانند تقسیم بر صفر و غیره. نمونه ای از آن در زیر آمده است.

fn main() {
    let result: f64 = 11.0 / 0.0;
    assert!(result.is_infinite());
} 
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نتیجه

امیدوارم این مقاله به شما کمک کرده باشد تا چیزی را که قبلاً نمی دانید درک کنید.

اگر این مطلب را ارزش خواندن می‌دانید، لطفاً فراموش نکنید که لایک کنید، نظرات خود را به اشتراک بگذارید و این مقاله را با دوستان و جامعه خود به اشتراک بگذارید زیرا این باعث تشویق من می‌شود. همچنین فراموش نکنید که در شبکه های اجتماعی که در مقدمه ذکر کردم با من در ارتباط باشید. اشتراک در من کانال یوتیوب همچنین اگر یک یادگیرنده بصری هستید برای محتوای مشابه. بیایید در مقاله بعدی همدیگر را ببینیم، خداحافظ 👋 تا آن زمان.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا