CodeGym/Blog Java/rawak/BigDecimal dalam Java
John Squirrels
Tahap
San Francisco

BigDecimal dalam Java

Diterbitkan dalam kumpulan
Hai! Dalam pelajaran hari ini, kita akan bercakap tentang nombor yang besar. Tidak, maksud saya SANGAT BESAR. Kami sebelum ini telah berulang kali menemui jadual julat nilai untuk jenis data primitif. Ia kelihatan seperti ini:
Jenis primitif Saiz dalam ingatan Julat nilai
bait 8 bit -128 hingga 127
pendek 16 bit -32768 hingga 32767
char 16 bit 0 hingga 65536
int 32 bit -2147483648 hingga 2147483647
panjang 64 bit -9223372036854775808 hingga 9223372036854775807
terapung 32 bit (2 kepada kuasa -149) kepada ((2 kepada kuasa -23) * 2 kepada kuasa 127)
berganda 64 bit (-2 kepada kuasa 63) kepada ((2 kepada kuasa 63) - 1)
boolean 8 (apabila digunakan dalam tatasusunan), 32 (apabila tidak digunakan dalam tatasusunan) betul atau salah
Jenis data integer yang paling lapang ialah long . Apabila ia datang kepada nombor titik terapung, ia adalah berganda . Tetapi bagaimana jika bilangan yang kita perlukan adalah terlalu besar sehingga ia tidak sesuai dengan yang panjang ? Jenis data Long mempunyai julat nilai yang mungkin agak besar, tetapi ia masih terhad kepada 64 bit. Apakah yang perlu kita buat jika Nombor Sangat Besar kita memerlukan 100 bit? Nasib baik, kita tidak perlu mencipta apa-apa. Untuk kes seperti ini, Java mempunyai dua kelas khas: BigInteger (untuk integer) dan BigDecimal(untuk nombor titik terapung). Apa yang membuatkan mereka istimewa? Pertama sekali, secara teori, mereka tidak mempunyai saiz maksimum. Kami mengatakan "dalam teori", kerana tidak ada komputer dengan memori yang tidak terhingga. Dan jika program anda mencipta nombor yang lebih besar daripada jumlah memori yang tersedia, maka, program itu tidak akan berfungsi, sudah tentu. Tetapi kes sedemikian tidak mungkin. Akibatnya, kita boleh mengatakan bahawa BigInteger dan BigDecimal boleh mewakili bilangan saiz yang hampir tidak terhad. Untuk apa kelas ini digunakan? Pertama sekali, untuk pengiraan dengan keperluan ketepatan yang sangat ketat. Sebagai contoh, kehidupan manusia mungkin bergantung pada ketepatan pengiraan dalam beberapa program (cth perisian yang mengawal kapal terbang, roket atau peralatan perubatan). Jadi jika tempat perpuluhan ke-150 adalah penting, maka BigDecimaladalah pilihan terbaik. Di samping itu, objek kelas ini sering digunakan dalam dunia kewangan, di mana pengiraan tepat walaupun nilai terkecil juga amat penting. Bagaimanakah anda bekerja dengan objek BigInteger dan BigDecimal dan adakah anda perlu tahu 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);
   }
}
Menghantar rentetan kepada pembina hanyalah satu pilihan yang mungkin. Di sini kami menggunakan rentetan, kerana nombor kami melebihi nilai maksimum untuk long dan double , dan kami memerlukan beberapa cara untuk menerangkan kepada pengkompil nombor yang ingin kami buat :) Cukup luluskan nombor 111111111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111111111111111111111111111111111111111 kepada pembina tidak akan berfungsi: Java akan cuba menjejalkan nombor yang diluluskan ke dalam salah satu jenis data primitif, tetapi ia tidak sesuai dengan mana-mana daripada mereka. Itulah sebabnya menggunakan rentetan untuk menghantar 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 ( Tidak boleh ubah ). Anda sudah biasa dengan kebolehubahan terima kasih kepada pengalaman anda dengan kelas String dan kelas pembalut untuk jenis primitif (Integer, Long, dll.).
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:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Seperti yang anda jangkakan, nombor kami tidak berubah. Untuk melaksanakan operasi tambah, anda mesti mencipta objek baharu untuk menerima hasil operasi.
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:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Lihat, kini 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 + - * /. Sebaliknya, mereka menyediakan satu set kaedah. Mari kita berkenalan dengan yang utama (seperti biasa, anda boleh menemui senarai lengkap kaedah dalam dokumentasi Oracle: di sini dan di sini ).
  1. kaedah untuk operasi aritmetik: tambah() , tolak() , darab() , bahagi() . Kaedah ini digunakan untuk melakukan penambahan, penolakan, pendaraban dan pembahagian, masing-masing.

  2. doubleValue() , intValue() , floatValue() , longValue() , dsb. digunakan untuk menukar nombor besar kepada salah satu jenis primitif Java. Berhati-hati apabila menggunakan kaedah ini. Jangan lupa tentang perbezaan saiz bit!

    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.
    Perhatikan bahawa kaedah ini 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

Tingkah laku pembundaran BigDecimal

Topik ini mempunyai bahagian tersendiri, memandangkan pembundaran nombor besar dan mengkonfigurasi gelagat pembundaran tidak begitu mudah. Anda boleh menggunakan kaedah setScale() untuk menetapkan bilangan tempat perpuluhan untuk BigDecimal . Sebagai contoh, katakan kita mahu nombor 111.5555555555 mempunyai tiga digit selepas titik perpuluhan. Walau bagaimanapun, kita tidak boleh mencapai apa yang kita mahu dengan menghantar nombor 3 sebagai hujah kepada kaedah setScale() . Seperti yang dinyatakan di atas, BigDecimaladalah untuk mewakili nombor dengan keperluan ketat pada ketepatan pengiraan. Dalam bentuk semasa, nombor kita mempunyai 10 digit selepas titik perpuluhan. Kami mahu menggugurkan 7 daripadanya dan mengekalkan hanya 3. Oleh itu, sebagai tambahan kepada nombor 3, kita mesti lulus mod pembundaran. BigDecimal mempunyai sejumlah 8 mod pembundaran. Itu banyak! Tetapi jika anda benar-benar perlu memperhalusi ketepatan pengiraan anda, anda akan mempunyai semua yang anda perlukan. Jadi, berikut ialah 8 mod pembundaran yang ditawarkan oleh BigDecimal :
  1. ROUND_CEILING — bulat ke atas

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN — bulat ke arah sifar

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

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

  4. ROUND_HALF_UP — bulatkan ke atas jika nombor selepas titik perpuluhan >= 0.5

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

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

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

    Nombor di sebelah kiri tempat perpuluhan ialah 2 (genap). Nombor dibundarkan ke bawah. Kami mahu 0 tempat perpuluhan, jadi hasilnya ialah 2.

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

    Nombor di sebelah kiri titik perpuluhan ialah 3 (ganjil). Nombor dibundarkan ke atas. Kami mahu 0 tempat perpuluhan, jadi hasilnya ialah 4.

  7. ROUND_UNNECCESSARY — Mod ini digunakan apabila anda mesti menghantar mod pembundaran kepada kaedah, tetapi nombor itu tidak perlu dibundarkan. Jika anda cuba membundarkan nombor dengan set mod ROUND_UNNECCESSARY, ArithmeticException dilemparkan.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP — pusingan dari sifar.

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

Membandingkan nombor besar

Ini juga penting. Anda akan ingat bahawa kami menggunakan kaedah equals() ialah membandingkan objek dalam Java. Pelaksanaan sama ada disediakan oleh bahasa itu sendiri (untuk kelas Java standard) atau ditindih oleh pengaturcara. Tetapi dalam kes objek BigDecimal , menggunakan kaedah equals() untuk perbandingan tidak disyorkan. Ini kerana kaedah BigDecimal.equals() mengembalikan benar hanya jika 2 nombor mempunyai nilai dan skala yang sama: Mari bandingkan kelakuan kaedah equals() untuk kelas Double dan 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, untuk BigDecimal , nombor 1.5 dan 1.50 ternyata tidak sama! Ini adalah tepat kerana spesifik pelaksanaan kaedah equals() dalam kelas BigDecimal . Untuk perbandingan yang lebih tepat bagi dua objek BigDecimal , lebih 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 bahawa 1.5 dan 1.50 adalah sama. Dan ini adalah hasil yang kami jangkakan! :) Itu mengakhiri pelajaran kita hari ini. Kini tiba masanya untuk kembali kepada tugas! :)
Komen
  • Popular
  • Baru
  • Tua
Anda mesti log masuk untuk meninggalkan ulasan
Halaman ini tidak mempunyai sebarang ulasan lagi