CodeGym /وبلاگ جاوا /Random-FA /NaN در جاوا
John Squirrels
مرحله
San Francisco

NaN در جاوا

در گروه منتشر شد
در جاوا، "NaN" مخفف "Not a Number" است. این یک نوع استثنا نیست، بلکه با کمال تعجب، نوع داده NaN نیز یک عدد است. اما اغلب زمانی که برنامه نویسان تازه کار به طور ناخواسته آن را دریافت می کنند، بیشتر از آن در محاسبات خود استفاده می کنند. از این رو، انواع داده های ناسازگار در جاوا هنگامی که با هم استفاده می شوند می توانند باعث خطای پرتاب شونده شوند. همچنین معمولاً دیده می شود که java.lang.ArithmeticException: / by zeroهمان NaN در نظر گرفته می شود. با این حال، جاوا با هر دو آنها متفاوت رفتار می کند. به اندازه کافی گیج کننده؟ برای درک جامع شما، تفاوت این دو را با یکدیگر تشریح خواهیم کرد. در پایان این مقاله با عملیات‌های احتمالی که یک عدد (nan) تولید نمی‌کنند، و چند راه آسان برای مدیریت آن آشنا خواهید شد.

NaN چیست؟

بنابراین، NaN چیست؟ "NaN" همانطور که بسیاری از شما حدس زده اید، برای نشان دادن "عدد نیست" در جاوا استفاده می شود. این یک مقدار ممیز شناور ویژه برای نشان دادن سرریزها و خطاها است. وقتی یک عدد ممیز شناور بر صفر تقسیم شود یا جذر یک عدد منفی محاسبه شود، تولید می شود. NaN در جاوا - 1برای مثال به قطعه زیر نگاهی بیندازید.
public class NaN
{
    public static void main(String[]args)
    {
        System.out.println(0.0 / 0.0);	  //zero divided by zero
        System.out.println(Math.sqrt(-1)); //take sqrt of negative number
        System.out.println(10.0 % 0);      //taking mod by zero
    }
}
خروجی

NaN                                                                                                                                           
NaN                                                                                                                                           
NaN
در قطعه بالا مشاهده می کنید که NaN در نتیجه 3 عملیات ساده تولید می شود:
  • تقسیم float / doubleصفر بر صفر.
  • زیر ریشه گرفتن یک عدد منفی (Math.sqrt(-x)). در ریاضیات، جذر یک عدد منفی، یک عدد خیالی به دست می‌آید . این مورد با برگرداندن NaN در جاوا حل می شود.
  • گرفتن mod از یک عدد با صفر، پس از تقسیم یک مقدار بر صفر، باقیمانده را برمی گرداند. بنابراین، NaN برگردانده می شود.

NaN چه تفاوتی با بی نهایت مثبت و منفی دارد؟

طبق مشخصات IEEE 754، سه مقدار ممیز شناور و مضاعف ویژه برای رسیدگی به موارد مرزی وجود دارد:
  • بی نهایت مثبت
  • بی نهایت منفی
  • NaN
حاصل تقسیم یک عدد مثبت بر 0 بی نهایت مثبت است. به همین ترتیب، بی نهایت منفی در نتیجه تقسیم یک عدد منفی با صفر به دست می آید. لطفاً توجه داشته باشید که تمام مقادیر ممیز شناور برای نوع داده double نیز قابل اعمال هستند. دقت محدود شناورها در مواقعی کافی نیست. با این حال، در بخش بعدی خواهیم دید که چگونه NaN برای هر دو شناور و دو برابر کار می کند.

روشNaN() چیست؟

isNaN()یکی از روش های اساسی در جاوا برای بررسی اینکه آیا مقدار NaN است یا خیر است. همانطور که در بالا به سه مورد اشاره کردیم، زمان آن رسیده است که روش isNaN() را بین مقادیر +infinity ، -infinity و NaN متمایز کند .
public class isNaN
{ public static void main(String[]args)
  {
    Double posInfinity = +2.0 / 0.0;
    Double negInfinity = -3.5 / 0.0;
    Double nanVal = 50 % 0.0;


    System.out.println ("+" + posInfinity + ".IsNaN() = " + posInfinity.isNaN());
    System.out.println ( negInfinity + ".IsNaN() = " + negInfinity.isNaN());
    System.out.println ( nanVal +  ".IsNaN() = " + nanVal.isNaN());
  }
}
خروجی

+Infinity.IsNaN() = false                                                                                                                       
-Infinity.IsNaN() = false                                                                                                                       
NaN.IsNaN() = true

چگونه مقادیر NaN را مقایسه کنیم؟

هر مقدار NaN متمایز در نظر گرفته می شود. این بدان معناست که یک NaN واحد با هیچ NaN دیگری برابر نیست. با این اصل، اگر یک مقدار را با مقدار دیگر مقایسه کنید، نتیجه همیشه منفی است. از آنجایی که NaN نامرتب است، بنابراین یک مقایسه عددی شامل حتی یک NaN منفرد، نادرست است. جاوا Float.NaN و Double.NaN را برای فیلدهای ثابت در هر دو کلاس برای انجام مقایسه فراهم می کند. ما می توانیم اینها را در دو سناریو جداگانه متمایز کنیم:
  • درست: فقط در صورت عدم تساوی (!=)
  • نادرست: برای همه عملوندهای مقایسه (==، <=، >=، <، >)
در اینجا یک نمونه کار برای شما بچه ها آورده شده است:
public class ComparingNaN
{ public static void main(String[] args)
  {
    // Comparing NaN values for Float constants
    System.out.println (Float.NaN != Float.NaN); // true
    System.out.println (Float.NaN == Float.NaN); // false
    System.out.println (Float.NaN < Float.NaN);  // false
    System.out.println (Float.NaN > Float.NaN);  // false
    System.out.println (Float.NaN <= Float.NaN); // false
    System.out.println (Float.NaN >= Float.NaN); // false

    // Comparing NaN values for Float constants
    System.out.println (Double.NaN != Double.NaN); // true
    System.out.println (Double.NaN == Double.NaN); // false
    System.out.println (Double.NaN < Double.NaN);  // false
    System.out.println (Double.NaN > Double.NaN);  // false
    System.out.println (Double.NaN <= Double.NaN); // false
    System.out.println (Double.NaN >= Double.NaN); // false
  }
}

چگونه مقادیر NaN تولید کنیم؟

قبل از جمع بندی، اجازه دهید به چند نمونه رایج از گرفتن یک عدد (nan) نگاه کنیم.
public class GenerateNaNValues {
  static final float ZERO = 0;
  public static void main (String[]args)
  {
    System.out.println("ZERO / ZERO = " + (ZERO / ZERO));
    System.out.println("+INFINITY - INFINITY = " +
    (Float.POSITIVE_INFINITY + Float.NEGATIVE_INFINITY));
    System.out.println("-INFINITY * ZERO = " + (Float.NEGATIVE_INFINITY * ZERO));
    System.out.println("+INFINITY * ZERO = " + (Float.POSITIVE_INFINITY * ZERO));
    System.out.println("log10(-10) = " +  Math.log(-10));
    System.out.println("√-10 = " + Math.sqrt(-10));
    System.out.println("NaN + 10 = " + (Float.NaN + 10));
    System.out.println("NaN - 10 = " + (Float.NaN - 10));
    System.out.println("NaN * 10 = " + (Float.NaN * 10));
    System.out.println("NaN / 10 = " + (Float.NaN / 10));
    System.out.println("NaN + NaN = " + (Float.NaN + Float.NaN));
    System.out.println("NaN - NaN = " + (Float.NaN - Float.NaN));
    System.out.println("NaN * NaN = " + (Float.NaN * Float.NaN));
    System.out.println("NaN / NaN = " + (Float.NaN / Float.NaN));
  }
}
خروجی:

ZERO / ZERO = NaN                                                                                                                               
+INFINITY - INFINITY = NaN                                                                                                                      
-INFINITY * ZERO = NaN                                                                                                                          
+INFINITY * ZERO = NaN                                                                                                                          
log10(-10) = NaN                                                                                                                                
√-10 = NaN                                                                                                                                      
NaN + 10 = NaN                                                                                                                                    
NaN - 10 = NaN                                                                                                                                  
NaN * 10 = NaN                                                                                                                                  
NaN / 10 = NaN                                                                                                                                  
NaN + NaN = NaN                                                                                                                                 
NaN - NaN = NaN                                                                                                                                 
NaN * NaN = NaN                                                                                                                                 
NaN / NaN = NaN

نتیجه

پس از مشاهده عملیات های متعدد تولید NaN، اکنون باید با آن آشنا شوید. ممکن است در ابتدا شما را متحیر کند، اما هیچ چیز پیچیده ای برای مقابله با آن وجود ندارد. با ایجاد یک عادت کوچک برای بررسی اینکه آیا یک مقدار NaN نیست در محاسبات مضاعف / ممیز شناور می تواند شما را از دردسرهای زیادی نجات دهد. حتی اگر در ابتدا این را فراموش کنید، کاملاً خوب است. همیشه می توانید برای عیب یابی جزئی به این مقاله مراجعه کنید. ایجاد کد قابل کامپایل و بدون خطا یکباره پس از سالها تجربه انجام می شود. پس بیایید دستمان را در کد کثیف کنیم و چیزی عالی بسازیم!
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION