JavaRush /Blog Java /Random-MS /BigDecimal dalam Java

BigDecimal dalam Java

Diterbitkan dalam kumpulan
hello! Dalam kuliah hari ini kita akan bercakap tentang bilangan yang besar. Tidak, tentang yang BENAR-BENAR BESAR. Sebelum ini , kami telah melihat jadual julat nilai untuk jenis data primitif lebih daripada sekali. Ia kelihatan seperti ini:
Jenis primitif Saiz dalam ingatan Julat nilai
bait 8 bit -128 hingga 127
pendek 16 bit kepada -32768 hingga 32767
char 16 bit dari 0 hingga 65536
int 32 bit daripada -2147483648 hingga 2147483647
panjang 64 bit daripada -9223372036854775808 hingga 9223372036854775807
terapung 32 bit daripada (2 kepada kuasa -149) kepada ((2-2 kepada kuasa -23)*2 kepada kuasa 127)
berganda 64 bit daripada (-2 kepada kuasa 63) kepada ((2 kepada kuasa 63) - 1)
boolean 8 (apabila digunakan dalam tatasusunan), 32 (apabila digunakan dalam bukan tatasusunan) betul atau salah
Jika kita bercakap tentang integer, jenis data yang paling luas ialah long , dan apabila kita bercakap tentang nombor titik terapung, double . Tetapi bagaimana jika bilangan yang kita perlukan adalah terlalu besar sehingga ia tidak sesuai dengan panjang ? Julat nilai Long yang mungkin agak besar, tetapi masih terhad kepada saiz tertentu - 64 bit. Apakah yang boleh kita buat jika Nombor Sangat Besar kita mempunyai berat 100 bit? Nasib baik, anda tidak perlu mencipta apa-apa. Di Jawa, dua kelas khas dicipta untuk kes sedemikian - BigInteger (untuk integer) dan BigDecimal (untuk nombor titik terapung). Apakah ciri mereka? Pertama sekali, mereka secara teorinya tidak mempunyai saiz maksimum. Secara teorinya, kerana tidak ada komputer dengan memori yang tidak terhingga. Dan jika anda mencipta nombor dalam program yang lebih besar daripada saiz memori komputer, sudah tentu, program itu tidak akan berfungsi. Tetapi kes sedemikian tidak mungkin. Oleh itu, kita boleh mengatakan bahawa saiz nombor boleh dikatakan BigIntegertidak BigDecimalterhad. Untuk apa kelas ini digunakan? Pertama sekali, untuk pengiraan dengan keperluan ketepatan yang sangat tinggi. Terdapat, sebagai contoh, program di mana kehidupan manusia boleh bergantung pada ketepatan pengiraan (perisian untuk kapal terbang dan roket atau untuk peralatan perubatan). Oleh itu, jika tempat perpuluhan ke-150 pun memainkan peranan penting, BigDecimalia adalah pilihan terbaik. Di samping itu, agak kerap objek ini digunakan dalam dunia kewangan, di mana ketepatan pengiraan hingga ke nilai terkecil juga sangat penting. Bagaimana untuk bekerja dengan objek BigIntegerdan BigDecimalapa yang penting untuk diingati tentangnya? Objek kelas ini dibuat seperti ini:
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);
   }
}
Melepasi rentetan sebagai parameter hanyalah salah satu daripada pembina yang mungkin. Di sini kami menggunakan rentetan kerana nombor kami melebihi nilai maksimum longdan double, dan entah bagaimana kami perlu menerangkan kepada pengkompil dengan tepat nombor yang kami mahu dapatkan :) Hanya lulus nombor 1111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111. 1111 tidak akan berfungsi: Java akan cuba "muat" nombor yang diluluskan ke dalam salah satu jenis data primitif, tetapi ia tidak akan dimuatkan dengan mana-mana daripada mereka. Oleh itu, menggunakan rentetan untuk lulus nombor yang dikehendaki adalah pilihan yang baik. Kedua-dua kelas boleh mengekstrak nilai berangka secara automatik daripada rentetan yang diluluskan. Satu lagi perkara penting yang perlu diingat apabila bekerja dengan kelas nombor besar ialah objeknya tidak boleh diubah ( Immutable) . Anda sudah mengetahui dengan baik prinsip kebolehubah melalui contoh kelas Stringdan kelas pembalut untuk primitif (Integer, Long dan lain-lain).
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);

   }
}
Output konsol:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Nombor kami tidak berubah, seperti yang anda jangkakan. Untuk operasi penambahan berjaya, anda mesti mencipta objek baharu dan menetapkan hasil penambahan kepadanya.
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);

   }
}
Output konsol:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Sekarang semuanya berfungsi sebagaimana mestinya :) By the way, adakah anda perasan betapa luar biasa operasi penambahan kelihatan?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Ini adalah satu lagi perkara penting. Kelas nombor besar tidak menggunakan operator +-*/ dalam operasinya, sebaliknya menyediakan satu set kaedah. Mari kita lihat yang utama (anda boleh, seperti biasa, mencari senarai lengkap kaedah dalam dokumentasi Oracle: di sini dan di sini ).
  1. kaedah untuk melaksanakan operasi aritmetik: add() , subtract(), multiply(), divide(). Digunakan untuk operasi tambah, tolak, darab dan bahagi masing-masing.

  2. doubleValue(), intValue(), floatValue(), longValue()dan lain-lain. - Digunakan untuk menukar nombor yang besar kepada jenis primitif Java. Berhati-hati apabila menggunakannya dan ingat perbezaan kapasiti!

    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);
    
       }
    }

    Output konsol:

    
    8198552921648689607
  3. min()dan max()- membolehkan anda mencari nilai minimum dan maksimum dua nombor besar yang diluluskan.
    Sila ambil perhatian: kaedah tidak statik!

    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));
    
       }
    }

    Output konsol:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

Kawalan pembundaran BigDecimal

Topik ini disertakan dalam bahagian yang berasingan, kerana membundarkan nombor yang besar dan melaraskannya bukanlah perkara yang mudah. Anda boleh menetapkan bilangan tempat perpuluhan untuk nombor BigDecimalmenggunakan setScale(). Sebagai contoh, kami ingin menetapkan ketepatan nombor 111.5555555555 kepada tiga tempat perpuluhan. Walau bagaimanapun, kami tidak akan dapat melepasi nombor 3 sebagai hujah kepada kaedah setScale()dan dengan itu menyelesaikan masalah kami. Seperti yang dinyatakan di atas, BigDecimalini adalah nombor untuk pengiraan dengan peningkatan ketepatan. Dalam bentuk semasa, nombor kita mempunyai 10 tempat perpuluhan. Kami ingin membuang 7 daripadanya dan meninggalkan hanya 3. Oleh itu, sebagai tambahan kepada nombor 3, kita mesti lulus mod pembundaran sebagai parameter . Terdapat 8 mod pembundaran secara keseluruhan BigDecimal. Agak banyak! Tetapi jika anda perlu benar-benar memperhalusi ketepatan pengiraan dalam program, anda akan mempunyai semua yang anda perlukan untuk ini. Jadi, berikut ialah 8 mod pembulatan yang terdapat dalam BigDecimal:
  1. ROUND_CEILING- Bundarkan

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

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- membulatkan ke bawah

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

  4. ROUND_HALF_UP— membundarkan jika nombor selepas titik perpuluhan >= .5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— membundarkan jika nombor selepas titik perpuluhan > .5

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— pembundaran akan bergantung pada nombor di sebelah kiri titik perpuluhan. Jika nombor di sebelah kiri genap, maka pembundaran akan dilakukan ke bawah. Jika nombor di sebelah kiri titik perpuluhan adalah ganjil, ia akan dibundarkan ke atas.

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

    Nombor di sebelah kiri titik perpuluhan - 2 - ialah genap. Pembundaran berlaku ke bawah. Oleh kerana kita memerlukan 0 tempat perpuluhan, hasilnya akan menjadi 2.

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

    Nombor di sebelah kiri titik perpuluhan - 3 - adalah ganjil. Pembundaran berlaku ke atas. Oleh kerana kita memerlukan 0 tempat perpuluhan, hasilnya ialah 4.

  7. ROUND_UNNECCESSARY— digunakan dalam kes di mana mod pembundaran perlu dihantar kepada beberapa kaedah, tetapi nombor itu tidak memerlukan pembundaran. Jika anda cuba membundarkan nombor apabila mod ROUND_UNNECCESSARY ditetapkan, ArithmeticException dilemparkan.

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

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

Perbandingan bilangan besar

Soalan ini juga penting. Anda sudah ingat bahawa kaedah ini digunakan untuk membandingkan objek dalam Java equals(). Ia sama ada disediakan oleh bahasa itu sendiri (dalam kes kelas terbina dalam Java) atau ditindih oleh pengaturcara. Tetapi dalam kes objek kelas, tidak disyorkan BigDecimaluntuk menggunakan kaedah equals()untuk perbandingan. Sebab untuk ini ialah BigDecimal.equals()kaedah dua nombor kembali benar hanya jika kedua-dua nombor mempunyai nilai dan skala yang sama : Mari kita bandingkan tingkah laku kaedah equals()y Doubledan y BigDecimal:
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));

   }
}
Output konsol:

true
false
Seperti yang anda lihat, nombor 1.5 dan 1.50 dalam kes c BigDecimalternyata tidak sama! Ini berlaku dengan tepat kerana kaedah khusus equals()dalam kelas BigDecimal. Untuk perbandingan yang lebih tepat dari kedua-duanya, BigDecimallebih baik menggunakan kaedah 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));

   }
}
Output konsol:

0
Kaedah compareTo()mengembalikan 0, yang bermaksud sama dengan 1.5 dan 1.50. Inilah hasil yang kami harapkan! :) Ini mengakhiri pelajaran kita untuk hari ini. Sudah tiba masanya untuk kembali ke tugas! :)
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION