CodeGym /Kurslar /C# SELF /Dəqiqlik problemləri və xüsusi dəyərlər

Dəqiqlik problemləri və xüsusi dəyərlər

C# SELF
Səviyyə, Dərs
Mövcuddur

1. Giriş

Elə bilirsən ki, kompüter "ağıllıdır", onda 0.1 + 0.2 sadəcə 0.3 olmalıdır. Amma bu tam belə deyil. Gəlin bunu sadə bir nümunədə yoxlayaq.

double x = 0.1;
double y = 0.2;
double sum = x + y;
Console.WriteLine(sum); // Proqram nə çap edəcək?
Həqiqi ədədlərin toplanması: 0.3 gözləyirik, bəs əslində nə olur?

İndi isə müqayisə et 0.3 ilə:

Console.WriteLine(sum == 0.3); // Burada true olacaq, yoxsa false?

Əgər False görsən, təəccüblənmə!

Səbəb ədədlərin yaddaşda necə saxlanmasındadır

Kompüterlər ədədlərlə ikilik sistemdə işləyir. Amma heç də bütün onluq kəsrləri sonlu ikilik kəsr kimi yazmaq olmur, elə 1/3 kimi onluq kəsrdə dəqiq yazmaq olmur (0.333...). Məsələn, 0.1 ikilikdə sonsuz kəsrdir və onu yaddaşda saxlamaq üçün "yuvarlaqlaşdırmaq" lazımdır.

Sadə dillə desək, double bəzən "elə göstərir" ki, sənin ədədini tam saxlayır, amma əslində çox yaxın bir təxmini dəyəri saxlayır.

2. double ilə arifmetikada hansı "gülməli şeylər" baş verir?

Gəlin praktik nümunələrə baxaq.

Nümunə 1. Klassik "sehr" 0.1 + 0.2

double a = 0.1;
double b = 0.2;
double sum = a + b;
Console.WriteLine(sum);            // 0.30000000000000004
Console.WriteLine(sum == 0.3);     // False

Kompüter 0.3 yox, 0.30000000000000004 çap etdi. Fərq kiçikdir, amma məsələn, maliyyə ilə məşğulsansa — bu artıq ciddi məsələdir.

Nümunə 2. İterativ toplama

double result = 0;
for (int i = 0; i < 10; i++)
{
    result += 0.1;
}
Console.WriteLine(result); // 0.9999999999999999

1.0 istədin — bir az az aldın. Yenə də səbəb double daxilindəki yuvarlaqlaşdırmadır.

Bu real məsələlərdə niyə vacibdir

Çoxları düşünür: "Nə fərqi var, kiçik səhvdir, nə olsun!" Gəlin ödənişlər dünyasından bir nümunəyə baxaq.

Tutaq ki, sənin internet-bankında 100 əməliyyat 0.1 avro ilə toplanır. Əgər proqramın hər iterasiyada bir yüz mininci avronu "itirirsə", bank səviyyəsində artıq real pul "itirmiş" olacaqsan. Bax, burada mühasib dərhal gəlib soruşacaq: "Bizim pullar hanı?!"

3. Həqiqi ədədləri düzgün necə müqayisə etmək lazımdır

double çox vaxt sənin gözlədiyin dəyəri tam saxlaya bilmir deyə, birbaşa == ilə müqayisə "aldada" bilər. Bunun əvəzinə adətən ədədlərin fərqinin modulunu müəyyən çox kiçik bir ədəd (epsilon) ilə müqayisə edirlər.

Yaxınlıqla müqayisə nümunəsi

double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 0.000001;

if (Math.Abs(a - b) < epsilon)
{
    Console.WriteLine("Demək olar ki, bərabərdir!"); // Belə müqayisə daha təhlükəsizdir
}

Burada deyirik: "Əgər ədədlər arasındakı fərq bir milyonda birindən azdırsa, onları bərabər sayırıq".

4. double üçün xüsusi dəyərlər: Infinity, NaN, -Infinity

double tipi təkcə ədədləri yox, həm də xüsusi dəyərləri saxlayır. Onlar elə vəziyyətlərdə yaranır ki, riyaziyyat müəllimi adi tələbəyə qəti qadağan edərdi.

Sonsuzluq (Infinity)

Bəs 1 bölünsə 0-a nə olar?

double result = 1.0 / 0.0;
Console.WriteLine(result); // Infinity

C#-da (və bir çox dillərdə) double üçün 0-a bölmə istisna atmır! Əvəzində nəticə xüsusi "müsbət sonsuzluq" dəyəri olur.

Minus sonsuzluq (-Infinity)

Əgər mənfi ədəd 0-a bölsən, mənfi sonsuzluq alırsan:

double result = -1.0 / 0.0;
Console.WriteLine(result); // -Infinity

"Ədəd deyil" (NaN — Not a Number)

Əgər tam qəribə bir şey etsən, məsələn, mənfi ədədin kvadrat kökünü hesablamağa çalışsan:

double result = Math.Sqrt(-1);
Console.WriteLine(result); // NaN

Və ya 0.0 / 0.0 bölməsinin nəticəsi:

double result = 0.0 / 0.0;
Console.WriteLine(result); // NaN

NaN — "real həyatda ədəd olmayan hər şey" deməkdir.

Xüsusi dəyərləri yoxlamaq

C#-da xüsusi dəyərləri yoxlamaq üçün funksiyalar var:

Console.WriteLine(double.IsInfinity(result));    // true əgər sonsuzluqsa
Console.WriteLine(double.IsNaN(result));         // true əgər NaN-dırsa

Cədvəl: double qeyri-adi əməliyyatlara necə reaksiya verir

Əməliyyat Nəticə double-da nə saxlanır
1.0 / 0.0
Infinity +∞
-1.0 / 0.0
-Infinity -∞
0.0 / 0.0
NaN Ədəd deyil
Math.Sqrt(-1)
NaN Ədəd deyil
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Ədədi dəqiqlik fərqi
Ədədi dəqiqlik fərqi
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Epsilon istifadə edərək müqayisə
Epsilon istifadə edərək müqayisə
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION