استفاده از عملگر == برای مقایسه اعداد اعشاری عموما جواب نخواهد داد و کار صحیحی نیست. از این جهت که اعداد، اساسا به صورت یک سری صفر و یک ذخیره شده و امکان ذخیره سازی کامل و دقیق قسمت اعشاری وجود ندارد.
برای مثال نوعهای double و float امکان ذخیره سازی دقیق عدد یک دهم را ندارند. عدد 1/10 به صورت ...0.000110011001100 ذخیره میشود (در حالت باینری) و مقایسه دقیق مقادیر ثابت 0.00011 یا 0.00011001100 با آن میسر نیست؛ چون دقت نهایی این اعداد متفاوت است.
در زبان #C، نوع double، مطابق استاندارد IEEE-754 تهیه شدهاست و تنها 15 رقم اعشار دقت دارد و ذخیره سازی اعداد اعشاری در آن، به یک گرد سازی نهایی ختم خواهد شد. بنابراین به دلیل وجود این rounding error طبیعی، امکان استفاده از عملگری مانند == جهت مقایسهی اعداد اعشاری همیشه پاسخ صحیحی را به همراه نخواهد داشت.
برای نمونه مثال زیر را بررسی کنید:
double d1 = 12.14;
double d2 = 12.13;
double d3 = d1 - d2; // Should be 0.01
bool check = (d3 == 0.01); // should be true
که یک چنین خروجی را به همراه دارد (حاصل آن برخلاف تصور مساوی 0.01 نیست):
روشی که برای حل این مساله پیشنهاد شدهاست، تفریق دو عدد از هم و مقایسهی نتیجهی آن با epsilon است؛ بجای مقایسه با صفر:
public static bool ApproxEquals(double d1, double d2)
{
const double epsilon = 2.2204460492503131E-16;
if (d1 == d2)
return true;
double tolerance = ((Math.Abs(d1) + Math.Abs(d2)) + 10.0) * epsilon;
double difference = d1 - d2;
return (-tolerance < difference && tolerance > difference);
}
متد فوق را در فایل
MathUtils کتابخانهی JSON.NET میتواند مشاهده کنید.
با این خروجی:
در این حالت میتوان نتیجه گرفت که d3 و 0.01 بسیار بسیار نزدیک به هم هستند؛ یا تقریبا مساوی.