JavaRush /Java Blogu /Random-AZ /Java-da BigDecimal

Java-da BigDecimal

Qrupda dərc edilmişdir
Salam! Bugünkü mühazirəmizdə böyük rəqəmlərdən danışacağıq. Xeyr, həqiqətən BÖYÜK olanlar haqqında. Əvvəllər ibtidai məlumat növləri üçün dəyər diapazonları cədvəlini bir dəfədən çox görmüşük. Bu belə görünür:
Primitiv tip Yaddaşdakı ölçü Dəyərlər diapazonu
bayt 8 bit -128-dən 127-yə qədər
qısa 16 bit -32768-dən 32767-ə qədər
char 16 bit 0-dan 65536-a qədər
int 32 bit -2147483648-dən 2147483647-yə qədər
uzun 64 bit -9223372036854775808-dən 9223372036854775807-ə qədər
sal 32 bit (2-dən gücə -149) ((2-2 gücə -23)*2 gücə 127)
ikiqat 64 bit (-2-dən 63-ün gücünə) ((2-nin 63-ün gücünə) - 1)
boolean 8 (massivlərdə istifadə edildikdə), 32 (qeyri massivlərdə istifadə edildikdə) doğru və ya yanlış
Əgər tam ədədlərdən danışırıqsa, ən tutumlu məlumat növü long , üzən nöqtəli ədədlərdən danışarkən isə double . Bəs ehtiyac duyduğumuz rəqəm o qədər böyükdürsə, hətta uzunluğa da sığmırsa ? Mümkün Uzun dəyərlər diapazonu olduqca böyükdür, lakin hələ də müəyyən bir ölçü ilə məhdudlaşır - 64 bit. Çox Böyük Nömrəmiz 100 bit ağırlığındadırsa, nə tapa bilərik? Xoşbəxtlikdən, heç bir şey icad etməyə ehtiyac yoxdur. Java-da belə hallar üçün iki xüsusi sinif yaradılmışdır - BigInteger (tam ədədlər üçün) və BigDecimal (üzən nöqtəli ədədlər üçün). Onların xüsusiyyəti nədir? Əvvəla, nəzəri olaraq onların maksimum ölçüsü yoxdur. Nəzəri cəhətdən, çünki sonsuz yaddaşa malik kompüterlər yoxdur. Və proqramda kompüterin yaddaşının ölçüsündən böyük rəqəm yaratsanız, təbii ki, proqram işləməyəcək. Amma belə hallar çətin ki. Buna görə də rəqəmlərin ölçüsünün praktiki olaraq qeyri-məhdud BigIntegerolduğunu söyləyə bilərik BigDecimal. Bu siniflər nə üçün istifadə olunur? İlk növbədə, son dərəcə yüksək dəqiqlik tələbləri ilə hesablamalar üçün. Məsələn, insan həyatının hesablamaların düzgünlüyündən asılı ola biləcəyi proqramlar var (təyyarələr və raketlər və ya tibbi avadanlıqlar üçün proqram təminatı). Buna görə də, hətta 150-ci onluq yer də mühüm rol oynayırsa, BigDecimalbu, ən yaxşı seçimdir. Bundan əlavə, bu obyektlər çox vaxt maliyyə dünyasında istifadə olunur, burada ən kiçik dəyərlərə qədər hesablamaların dəqiqliyi də son dərəcə vacibdir. Obyektlərlə necə işləmək BigIntegerBigDecimalonlar haqqında nəyi yadda saxlamaq vacibdir? Bu siniflərin obyektləri belə yaradılmışdır:
public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
       System.out.println(decimal);
   }
}
Bir sətri parametr kimi ötürmək mümkün konstruktorlardan yalnız biridir. Burada biz sətirlərdən istifadə edirik, çünki nömrələrimiz maksimum dəyərləri aşır longdouble, və birtəhər kompilyatora dəqiq hansı rəqəmi almaq istədiyimizi izah etməliyik :) Sadəcə 111111111111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111 konstruktora 1111111111111111111111111111111111111111111111 1111 işləməyəcək: Java çalışacaq Keçirilmiş nömrəni primitiv məlumat növlərindən birinə "uyğunlaşdırın", lakin heç birinə uyğun gəlməyəcək. Buna görə də, istədiyiniz nömrəni ötürmək üçün sətirdən istifadə etmək yaxşı seçimdir. Hər iki sinif avtomatik olaraq ötürülən sətirlərdən rəqəmli dəyərlər çıxara bilər. Böyük sayda siniflərlə işləyərkən yadda saxlamaq lazım olan digər vacib məqam onların obyektlərinin dəyişməz olmasıdır ( Immutable) . StringSiz ibtidailər (Integer, Long və başqaları) üçün sinif və sarğı sinifləri nümunəsi vasitəsilə dəyişməzlik prinsipi ilə artıq yaxşı tanışsınız .
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       integer.add(BigInteger.valueOf(33333333));
       System.out.println(integer);

   }
}
Konsol çıxışı:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Nömrələrimiz gözlədiyiniz kimi dəyişməyib. Əlavə əməliyyatının uğurlu olması üçün siz yeni obyekt yaratmalı və əlavənin nəticəsini ona təyin etməlisiniz.
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigInteger result = integer.add(BigInteger.valueOf(33333333));
       System.out.println(result);

   }
}
Konsol çıxışı:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
İndi hər şey lazım olduğu kimi işləyir :) Yeri gəlmişkən, əlavə əməliyyatının necə qeyri-adi göründüyünü gördünüzmü?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Bu başqa bir vacib məqamdır. Çoxsaylı siniflər öz əməliyyatlarında +-*/ operatorlarından istifadə etmirlər, əksinə metodlar toplusunu təqdim edirlər. Əsas olanlara nəzər salaq (hər zaman olduğu kimi, metodların tam siyahısını Oracle sənədlərində tapa bilərsiniz: buradaburada ).
  1. arifmetik əməllərin yerinə yetirilməsi üsulları: add() , subtract(), multiply(), divide(). Müvafiq olaraq toplama, çıxma, vurma və bölmə əməliyyatları üçün istifadə olunur.

  2. doubleValue(), intValue(), floatValue()longValue()s. - Böyük ədədi Java primitiv tipinə çevirmək üçün istifadə olunur. Onlardan istifadə edərkən diqqətli olun və tutum fərqini unutmayın!

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
    
           long result = integer.longValue();
           System.out.println(result);
    
       }
    }

    Konsol çıxışı:

    
    8198552921648689607
  3. min()max()- keçən iki böyük ədədin minimum və maksimum qiymətini tapmağa imkan verir.
    Diqqət edin: üsullar statik deyil!

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
           BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");
    
           System.out.println(integer.max(integer2));
    
       }
    }

    Konsol çıxışı:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDecimal yuvarlaqlaşdırma nəzarəti

Bu mövzu ayrıca bölməyə daxil edilmişdir, çünki böyük rəqəmləri yuvarlaqlaşdırmaq və onu tənzimləmək o qədər də sadə bir şey deyil. BigDecimal-dan istifadə edərək nömrə üçün onluq yerlərin sayını təyin edə bilərsiniz setScale(). Məsələn, biz 111.5555555555 rəqəminin dəqiqliyini üç onluq yerə təyin etmək istəyirik. Ancaq biz 3 rəqəmini metoda arqument kimi ötürə bilməyəcəyik setScale()və bununla da problemimizi həll edə bilməyəcəyik. Yuxarıda qeyd edildiyi kimi, BigDecimalbunlar artan dəqiqliklə hesablamalar üçün rəqəmlərdir. İndiki formada sayımız 10 onluqdan ibarətdir. Biz onlardan 7-ni atmaq və yalnız 3-ü tərk etmək istəyirik. Buna görə də, 3 rəqəminə əlavə olaraq, yuvarlaqlaşdırma rejimini parametr kimi keçməliyik . Ümumilikdə 8 yuvarlaqlaşdırma rejimi var BigDecimal. Olduqca çox! Ancaq proqramda hesablamaların düzgünlüyünü həqiqətən tənzimləmək lazımdırsa, bunun üçün lazım olan hər şeyə sahib olacaqsınız. Beləliklə, burada mövcud olan 8 yuvarlaqlaşdırma rejimi var BigDecimal:
  1. ROUND_CEILING- yuvarlaqlaşdırma

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- axıdmanın atılması

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- aşağı yuvarlaqlaşdırma

    111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555

  4. ROUND_HALF_UP— ondalık nöqtədən sonrakı rəqəm >= olarsa yuvarlaqlaşdırma.5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— ondalıq nöqtədən sonrakı rəqəm > .5 olarsa yuvarlaqlaşdırma

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— yuvarlaqlaşdırma onluq nöqtənin solundakı rəqəmdən asılı olacaq. Soldakı rəqəm cütdürsə, yuvarlaqlaşdırma aşağıya doğru aparılacaq. Onluq nöqtənin solundakı rəqəm təkdirsə, yuvarlaqlaşdırılacaq.

    2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2

    Onluq nöqtənin solundakı rəqəm - 2 - cütdür. Yuvarlaqlaşdırma aşağı baş verir. 0 onluq yer tələb etdiyimiz üçün nəticə 2 olacaq.

    3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4

    Onluq nöqtənin solunda olan rəqəm - 3 - təkdir. Yuvarlaqlaşdırma yuxarıya doğru baş verir. 0 onluq yer tələb etdiyimiz üçün nəticə 4 olacaq.

  7. ROUND_UNNECCESSARY— yuvarlaqlaşdırma rejiminin hansısa üsula keçməsi lazım olduğu, lakin nömrənin yuvarlaqlaşdırılmasına ehtiyac olmadığı hallarda istifadə olunur. ROUND_UNNECCESSARY rejimi qurulduqda rəqəmi yuvarlaqlaşdırmağa cəhd etsəniz, ArithmeticException atılır.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP- yuvarlaqlaşdırma.

    111.5551 -> setScale(3, ROUND_UP) -> 111.556

Böyük ədədlərin müqayisəsi

Bu sual da vacibdir. Artıq xatırlayırsınız ki, metod Java-da obyektləri müqayisə etmək üçün istifadə olunur equals(). O, ya dilin özü tərəfindən təmin edilir (Java-nın daxili sinifləri vəziyyətində) və ya proqramçı tərəfindən ləğv edilir. Lakin sinif obyektləri vəziyyətində müqayisə üçün BigDecimalmetoddan istifadə etmək tövsiyə edilmir. equals()Bunun səbəbi odur ki, BigDecimal.equals()iki ədəd metodu yalnız iki ədəd eyni dəyər və miqyasda olduqda doğru qaytarır: Gəlin y və y metodlarının davranışını müqayisə edək : equals()DoubleBigDecimal
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       Double a = 1.5;
       Double b = 1.50;

       System.out.println(a.equals(b));

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.equals(y));

   }
}
Konsol çıxışı:

true
false
Gördüyünüz kimi, c halında 1.5 və 1.50 rəqəmləri BigDecimalqeyri-bərabər çıxdı! equals()Bu, məhz sinifdəki metodun xüsusiyyətlərinə görə baş verdi BigDecimal. İkisini daha düzgün müqayisə etmək üçün BigDecimalmetoddan istifadə etmək daha yaxşıdır compareTo():
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.compareTo(y));

   }
}
Konsol çıxışı:

0
Metod compareTo()0 qaytardı, bu da 1,5 və 1,50-yə bərabər deməkdir. Bu, ümid etdiyimiz nəticədir! :) Bununla bugünkü dərsimiz yekunlaşır. Tapşırıqlara qayıtmağın vaxtı gəldi! :)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION