JavaRush /Java blogi /Random-UZ /Java-da BigDecimal

Java-da BigDecimal

Guruhda nashr etilgan
Salom! Bugungi ma'ruzamizda biz katta raqamlar haqida gapiramiz. Yo'q, HAQIQATDA KATTA bo'lganlar haqida. Ilgari biz ibtidoiy ma'lumotlar turlari uchun qiymat diapazonlari jadvalini bir necha marta ko'rganmiz. Bu shunday ko'rinadi:
Primitiv tip Xotiradagi o'lcham Qiymatlar diapazoni
bayt 8 bit -128 dan 127 gacha
qisqa 16 bit -32768 dan 32767 gacha
char 16 bit 0 dan 65536 gacha
int 32 bit -2147483648 dan 2147483647 gacha
uzoq 64 bit -9223372036854775808 dan 9223372036854775807 gacha
suzmoq 32 bit dan (2 quvvatga -149) gacha ((2-2 quvvatga -23)*2 quvvatga 127)
ikki barobar 64 bit dan (-2 ning 63 darajasiga) ((2 ning 63 ning darajasiga) - 1) gacha
mantiqiy 8 (massivlarda foydalanilganda), 32 (massiv bo'lmaganlarda ishlatilganda) To'g'ri yoki noto'g'ri
Agar butun sonlar haqida gapiradigan bo'lsak, eng sig'imli ma'lumotlar turi long , va biz suzuvchi nuqtali raqamlar haqida gapirganda, double . Ammo bizga kerak bo'lgan raqam shunchalik katta bo'lsa-chi, u hatto uzunlikka ham sig'masa ? Mumkin bo'lgan Long qiymatlari diapazoni juda katta, ammo ma'lum bir o'lcham bilan cheklangan - 64 bit. Agar bizning juda katta raqamimiz 100 bit og'irlikda bo'lsa, biz nimani o'ylab topishimiz mumkin? Yaxshiyamki, siz hech narsa ixtiro qilishingiz shart emas. Java-da bunday holatlar uchun ikkita maxsus sinf yaratilgan - BigInteger (butun sonlar uchun) va BigDecimal (suzuvchi nuqtali raqamlar uchun). Ularning xususiyati nimada? Birinchidan, ular nazariy jihatdan maksimal hajmga ega emas. Nazariy jihatdan, chunki cheksiz xotiraga ega kompyuterlar yo'q. Va agar siz dasturda kompyuter xotirasi hajmidan kattaroq raqam yaratsangiz, albatta, dastur ishlamaydi. Ammo bunday holatlar ehtimoldan yiroq emas. Shuning uchun raqamlarning hajmi amalda cheklanmagan BigIntegerdeb aytishimiz mumkin. BigDecimalBu sinflar nima uchun ishlatiladi? Avvalo, juda yuqori aniqlik talablari bilan hisob-kitoblar uchun. Masalan, inson hayoti hisob-kitoblarning to'g'riligiga bog'liq bo'lishi mumkin bo'lgan dasturlar mavjud (samolyotlar va raketalar yoki tibbiy asbob-uskunalar uchun dasturiy ta'minot). Shuning uchun, agar 150-sonli kasr muhim rol o'ynasa, BigDecimalbu eng yaxshi tanlovdir. Bundan tashqari, ko'pincha bu ob'ektlar moliya olamida qo'llaniladi, bu erda eng kichik qiymatlargacha hisob-kitoblarning aniqligi ham juda muhimdir. Ob'ektlar bilan qanday ishlash kerak BigIntegerva BigDecimalular haqida nimani yodda tutish kerak? Ushbu sinflarning ob'ektlari quyidagicha yaratilgan:
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);
   }
}
Satrni parametr sifatida o'tkazish mumkin bo'lgan konstruktorlardan faqat bittasidir. Bu erda biz satrlardan foydalanamiz, chunki bizning raqamlarimiz maksimal qiymatlardan oshadi longva doubleva qandaydir tarzda kompilyatorga aynan qaysi raqamni olishni istayotganimizni tushuntirishimiz kerak :) Shunchaki 1111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111 konstruktorga 111111111111111111111111111111111111111111111111 1111 ishlamaydi: Java harakat qiladi O'tkazilgan raqamni ibtidoiy ma'lumotlar turlaridan biriga "moslash" mumkin, lekin u ularning hech biriga mos kelmaydi. Shuning uchun, kerakli raqamni o'tkazish uchun satrdan foydalanish yaxshi variantdir. Ikkala sinf ham o'tgan satrlardan raqamli qiymatlarni avtomatik ravishda chiqarishi mumkin. Katta sonli sinflar bilan ishlashda eslash kerak bo'lgan yana bir muhim jihat shundaki, ularning ob'ektlari o'zgarmasdir ( Immutable) . StringSiz ibtidoiylar (Integer, Long va boshqalar) uchun sinf va o'rash sinflari misolida o'zgarmaslik printsipi bilan allaqachon yaxshi tanishsiz .
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 chiqishi:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Bizning raqamlarimiz siz kutganingizdek o'zgarmadi. Qo'shish operatsiyasi muvaffaqiyatli bo'lishi uchun siz yangi ob'ekt yaratishingiz va unga qo'shish natijasini belgilashingiz kerak.
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 chiqishi:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Endi hamma narsa kerakli darajada ishlaydi :) Aytgancha, qo'shish operatsiyasi qanday g'ayrioddiy ko'rinishini sezdingizmi?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Bu yana bir muhim nuqta. Ko'p sonli sinflar o'z ishlarida +-*/ operatorlaridan foydalanmaydilar, aksincha, usullar to'plamini taqdim etadilar. Keling, asosiylarini ko'rib chiqaylik (siz har doimgidek, Oracle hujjatlarida usullarning to'liq ro'yxatini topishingiz mumkin: bu erda va bu erda ).
  1. arifmetik amallarni bajarish usullari: add() , subtract(), multiply(), divide(). Qo'shish, ayirish, ko'paytirish va bo'lish amallari uchun ishlatiladi.

  2. doubleValue(), intValue(), floatValue(), longValue()va boshqalar. - Katta sonni Java primitiv turiga aylantirish uchun foydalaniladi. Ulardan foydalanganda ehtiyot bo'ling va sig'imdagi farqni unutmang!

    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 chiqishi:

    
    8198552921648689607
  3. min()va max()- o'tkazilgan ikkita katta sonning minimal va maksimal qiymatini topish imkonini beradi.
    E'tibor bering: usullar statik emas!

    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 chiqishi:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDecimal yaxlitlashni boshqarish

Ushbu mavzu alohida bo'limga kiritilgan, chunki katta raqamlarni yaxlitlash va uni sozlash unchalik oddiy ish emas. BigDecimaldan foydalanib, raqam uchun kasrlar sonini belgilashingiz mumkin setScale(). Misol uchun, biz 111.5555555555 raqamining aniqligini uchta kasrga o'rnatmoqchimiz. Biroq, biz 3 raqamini usulga argument sifatida o'tkaza olmaymiz setScale()va shu bilan muammomizni hal qila olmaymiz. Yuqorida aytib o'tilganidek, BigDecimalbu yuqori aniqlikdagi hisob-kitoblar uchun raqamlar. Hozirgi ko'rinishida bizning raqamimiz 10 kasrdan iborat. Biz ulardan 7 tasini tashlab, faqat 3 tasini qoldirmoqchimiz. Shuning uchun, 3 raqamiga qo'shimcha ravishda, yaxlitlash rejimini parametr sifatida o'tkazishimiz kerak . Hammasi bo'lib 8 ta yaxlitlash rejimi mavjud BigDecimal. Juda ko'p! Ammo agar siz dasturda hisob-kitoblarning aniqligini chindan ham sozlashingiz kerak bo'lsa, buning uchun kerak bo'lgan hamma narsaga ega bo'lasiz. Shunday qilib, 8 ta yaxlitlash rejimi mavjud BigDecimal:
  1. ROUND_CEILING- yaxlitlash

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- zaryadsizlanish

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- yaxlitlash

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

  4. ROUND_HALF_UP— yaxlitlash, agar kasrdan keyingi raqam >= .5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— yaxlitlash, agar kasrdan keyingi raqam > .5 bo'lsa

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— yaxlitlash kasrning chap tomonidagi raqamga bog'liq bo'ladi. Agar chapdagi raqam juft bo'lsa, yaxlitlash pastga qarab amalga oshiriladi. Agar kasrning chap tomonidagi raqam toq bo'lsa, u yaxlitlanadi.

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

    Kasrning chap tomonidagi raqam - 2 - juft. Yaxlitlash pastga tushadi. Bizga 0 kasr kerak bo'lganligi sababli, natija 2 bo'ladi.

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

    Kasrning chap tomonidagi raqam - 3 - toq. Yaxlitlash yuqoriga qarab sodir bo'ladi. Bizga 0 kasr kerak bo'lganligi sababli, natija 4 bo'ladi.

  7. ROUND_UNNECCESSARY— yaxlitlash rejimini qandaydir usulga o'tkazish kerak bo'lgan hollarda qo'llaniladi, lekin raqamni yaxlitlash kerak emas. Agar siz ROUND_UNNECCESSARY rejimi o‘rnatilganda raqamni yaxlitlashga harakat qilsangiz, ArithmeticException chiqariladi.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP- yaxlitlash.

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

Katta sonlarni taqqoslash

Bu savol ham muhim. Usul Java'dagi ob'ektlarni solishtirish uchun ishlatilishini allaqachon eslaysiz equals(). U tilning o'zi tomonidan taqdim etiladi (Java o'rnatilgan sinflarida) yoki dasturchi tomonidan bekor qilinadi. Ammo sinf ob'ektlari bo'lsa, taqqoslash uchun BigDecimalusuldan foydalanish tavsiya etilmaydi. equals()Buning sababi shundaki, BigDecimal.equals()ikkita raqam usuli faqat ikkita raqam bir xil qiymat va masshtabga ega bo'lsa, rostni qaytaradi: y va y usullarining xatti-harakatlarini taqqoslaylik : 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 chiqishi:

true
false
Ko'rib turganingizdek, c holatidagi 1,5 va 1,50 raqamlari BigDecimaltengsiz bo'lib chiqdi! equals()Bu sinfdagi usulning o'ziga xos xususiyatlari tufayli sodir bo'ldi BigDecimal. Ikkalasini to'g'ri taqqoslash uchun BigDecimalusuldan foydalanish yaxshiroqdir 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 chiqishi:

0
Usul compareTo()0 ni qaytardi, ya'ni 1,5 va 1,50 ga teng. Bu biz umid qilgan natija! :) Shu bilan bugungi darsimiz yakunlanadi. Vazifalarga qaytish vaqti keldi! :)
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION