CodeGym /Kurslar /Java SELF AZ /Ədədi nöqtəli rəqəmlərlə işləmək nüansları

Ədədi nöqtəli rəqəmlərlə işləmək nüansları

Java SELF AZ
Səviyyə , Dərs
Mövcuddur

1. Vergüllü ədədlərin yuvarlanması

Artıq danışmışdıq ki, int tipli dəyişənin içinə vergüllü ədəd yazanda onun tam hissəsi saxlanılır, qalan hissə isə sadəcə atılır.

Amma elə hallar ola bilər ki, vergüllü ədədi sadəcə ən yaxın tam ədədə və ya ümumiyyətlə yuxarı yuvarlamaq lazım gəlsin. Bu halda nə etməli?

Bu və bu kimi bir çox hallarda Java-da Math sinfi yerləşir və onun round(), ceil(), floor() adlanan metodları var.


Math.round() metodu

Math.round() metodu ədədi ən yaxın tam ədədə yuvarlayır:

long x = Math.round(vergullu_eded)

Amma, necə deyərlər, bir nüans var: bu metodun nəticəsinin tipi — long (yəni int deyil). Vergüllü ədədlər çox böyük ola bilərlər deyə, Java yaradıcıları bu işlər üçün Java-da olan ən böyük tam ədəd tipini seçib — long.

Buna görə də nəticəni int tipli dəyişənə yazmaq üçün proqramçı kompilyatora açıq şəkildə bildirməlidir ki, məlumatların bir qisminin itməsi ehtimalını qəbul edir (əgər ədəd int tipinə uyğun olmazsa).

int x = (int) Math.round(vergullu_eded)

Nümunələr:

Əmr Nəticə
int x = (int) Math.round(4.1);
4
int x = (int) Math.round(4.5);
5
int x = (int) Math.round(4.9);
5

Math.ceil() metodu

Math.ceil() metodu ədədi ən yaxın tam ədədə yuxarı yuvarlayır, nümunələr:

Əmr Nəticə
int x = (int) Math.ceil(4.1);
5
int x = (int) Math.ceil(4.5);
5
int x = (int) Math.ceil(4.9);
5

Math.floor() metodu

Math.floor() metodu ədədi ən yaxın tam ədədə aşağı yuvarlayır, nümunələr:

Əmr Nəticə
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

Hətta, bir ədədi ən yaxın tam ədədə aşağı yuvarlamaq üçün sadəcə tip çevirmə operatorundan istifadə etmək daha sadə olar — (int):

Əmr Nəticə
int x = (int) 4.9
4

Əgər bu əmrləri yadda saxlamaq çətindirsə, sizə kiçik bir ingilis dili dərsi kömək edər:

  • Math — riyaziyyat
  • Round — dairə/yuvarlamaq
  • Ceiling — tavan
  • Floor — yer


2. Üzən nöqtəli ədədlərin quruluşu

double tipi -1.7*10308 ilə +1.7*10308 diapazonunda olan dəyərləri saxlanıla bilər. Bu cür böyük diapazon (müqayisədə int tipi ilə) onunla izah olunur ki, double tipi (float kimi) tam tiplərdən fərqli olaraq tamamilə başqa cür təşkil olunub. Hər bir double tipindəki dəyişən iki ədəd saxlayır: birinciyə mantissa, ikincisinə isə dərəcə deyilir.

Tutaq ki, bizdə 123456789 sayı var və biz onu double tipindəki dəyişəndə saxlayırıq. O zaman bu ədəd belə bir formata çevriləcək: 1.23456789*108double tipində iki ədəd saxlanacaq — 234567898. Qırmızı ilə «ədədin əhəmiyyətli hissəsi» (mantissa), mavi ilə dərəcə vurğulanıb.

Bu yanaşma həm çox böyük, həm də çox kiçik ədədləri saxlamağa imkan verir. Amma, çünki ədədin ölçüsü 8 bayt (64 bit) ilə məhdudlaşır və bəzi bitlər dərəcənin (eləcə də ədədin işarəsi və dərəcənin işarəsi) saxlanılması üçün istifadə olunur, maksimum mantissanın uzunluğu 15 rəqəm ilə məhdudlaşır.

Bu, həqiqi ədədlərin quruluşunun çox sadələşdirilmiş təsviridir, daha tam məlumatı bu linkdə tapa bilərsiz.


3. Vergüllü ədədlərlə işləyərkən dəqiqlik itkisi

Vergüllü ədədlərlə işləyərkən həmişə yadda saxlamaq lazımdır ki, vergüllü ədədlər dəqiq deyil. Həmişə yuvarlaqlaşdırma xətaları, onluq sistemdən ikilik sistemə çevirmə xətaları və nəhayət, ən çox rast gəlinən vəziyyət – dəqiqlik itkisi fərqli böyüklüklərə malik ədədləri toplama/çıxma əməliyyatlarında olur.

Sonuncu vəziyyət proqramlaşdırmaya yeni başlayanlar üçün ən gözlənilməzdir.

Əgər ədəddən 109 1/109 çıxsaq, yenidən 109 alırıq.

Çox fərqli böyüklüklərə malik ədədlərin çıxılması İzah
 1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
İkinci ədəd çox kiçikdir və onun irəli gələn hissəsi (boz rənglə işarələnib) nəzərə alınmır. Narıncı ilə 15 irəli gələn rəqəm işarələnib.

Nə deyək, proqramlaşdırma – riyaziyyat deyil.


4. Həqiqi rəqəmlərin müqayisəsinin təhlükəsi

Həqiqi rəqəmlərin müqayisəsi zamanı proqramçılar başqa bir təhlükə ilə qarşılaşa bilərlər. Çünki bu rəqəmlərlə işləyərkən yuvarlaqlaşdırma səhvləri yığıla bilər və vəziyyət yaranar ki, həqiqi rəqəmlər bərabər olmalı, amma bərabər olmazlar. Və əksinə: rəqəmlər bərabər olmamalı, amma bərabər olarlar.

Nümunə:

Komanda İzah
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
a dəyişənində dəyər 1000000000.0 olacaq
c dəyişənində dəyər 1000000000.0 olacaq
(b dəyişənindəki rəqəm çox kiçikdir)

Yuxarıdakı nümunədə ac bərabər olmamalı idi, amma onlar bərabərdir.

Başqa bir nümunəyə baxaq:

Komanda İzah
double a = 1.00000000000000001;
double b = 1.00000000000000002;
a dəyişənində dəyər 1.0 olacaq
b dəyişənində dəyər 1.0 olacaq

5. strictfp haqqında maraqlı fakt

Java-da xüsusi bir açar söz strictfp (strict floating point) var ki, digər proqramlaşdırma dillərində yoxdur. Bilirsiniz, bu nə üçün lazımdır? O, həqiqi rəqəmlərlə işləyərkən dəqiqliyi pisləşdirir. Bunun ortaya çıxma hekayəsi təxminən belədir:

Java yaradıcısı:
Biz çox istəyirik ki, Java superpopulyar olsun və Java-dakı proqramlar mümkün qədər çox cihazda işləsin. Buna görə də, Java maşınının spesifikasiyasında qeyd etdik ki, bütün cihazlarda bütün proqramlar eynilə işləməlidir!
Intel prosessor yaradıcısı:
Dostlar, biz prosessorlarımızı təkmilləşdirdik, və indi bütün həqiqi rəqəmlər prosessorun içində 8 deyil, 10 baytla təqdim olunacaq. Daha çox bayt — daha çox əlamətdar rəqəm deməkdir. Yəni nə? Doğru: indi elmi hesablamalarınız daha dəqiq olacaq!
Elm adamları və dəqiq hesablamalarla məşğul olan hər kəs:
Möhtəşəm! Əla xəbər. Aferin.
Java yaradıcısı:
Yo-yo-yo, dostlar. Biz dedik ki: bütün Java proqramları bütün cihazlarda eynilə işləməlidir. Intel prosessorlarının daxilində 10 baytlıq həqiqi rəqəmlərin istifadəsini məcburi şəkildə söndürürük.
İndi hər şey yenidən əladır! Təşəkkür etməyin.
Elm adamları və dəqiq hesablamalarla məşğul olan hər kəs:
Siz tamamilə ağlınızı itirmisiniz? Dərhal hər şeyi əvvəlki vəziyyətə qaytarın!
Java yaradıcısı:
Dostlar, bu sizin xeyriniz üçün idi! Təsəvvür edin: bütün Java proqramları bütün cihazlarda eyni işləyir. Möhtəşəm deyilmi!
Elm adamları və dəqiq hesablamalarla məşğul olan hər kəs:
Xeyr. Heç də möhtəşəm deyil. Dərhal hər şeyi əvvəlki vəziyyətə qaytarın! Yoxsa biz sizin Java-nı bilirsiniz haraya qoyarıq?
Java yaradıcısı:
Hm. Niyə bunu əvvəldən demədiniz. Əlbəttə, qaytaracağıq.
Bütün müasir prosessorların funksiyalarından istifadə imkanını bərpa etdik.
Bu arada. Biz dilə xüsusi olaraq strictfp sözünü əlavə etdik: əgər bir funksiya adından əvvəl onu yazsanız, həmin funksiyada həqiqi rəqəmlərlə iş bütün cihazlarda eyni dərəcədə pis olacaq!
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION