CodeGym /Java Blog /Acak /BigDecimal di Jawa
John Squirrels
Level 41
San Francisco

BigDecimal di Jawa

Dipublikasikan di grup Acak
Hai! Dalam pelajaran hari ini, kita akan berbicara tentang bilangan besar. Tidak, maksud saya BENAR-BENAR BESAR. Kami sebelumnya telah berulang kali menemukan tabel rentang nilai untuk tipe data primitif. Ini terlihat seperti ini:
Tipe primitif Ukuran dalam memori Kisaran nilai
byte 8 bit -128 hingga 127
pendek 16 bit -32768 hingga 32767
arang 16 bit 0 hingga 65536
int 32 bit -2147483648 hingga 2147483647
panjang 64 bit -9223372036854775808 ke 9223372036854775807
mengambang 32 bit (2 pangkat -149) menjadi ((2 pangkat -23) * 2 pangkat 127)
dobel 64 bit (-2 pangkat 63) ke ((2 pangkat 63) - 1)
boolean 8 (bila digunakan dalam array), 32 (bila tidak digunakan dalam array) benar atau salah
Tipe data integer yang paling lapang adalah long . Ketika datang ke angka floating-point, itu adalah double . Tetapi bagaimana jika jumlah yang kita butuhkan sangat besar sehingga tidak muat lagi ? Tipe data Long memiliki rentang kemungkinan nilai yang cukup besar, namun masih terbatas pada 64 bit. Apa yang perlu kita pikirkan jika Angka Sangat Besar kita membutuhkan 100 bit? Untungnya, kita tidak perlu menemukan apa pun. Untuk kasus seperti ini, Java memiliki dua kelas khusus: BigInteger (untuk bilangan bulat) dan BigDecimal(untuk angka titik-mengambang). Apa yang membuat mereka istimewa? Pertama-tama, secara teori, mereka tidak memiliki ukuran maksimal. Kami mengatakan "dalam teori", karena tidak ada komputer dengan memori tak terbatas. Dan jika program Anda membuat angka yang lebih besar dari jumlah memori yang tersedia, maka program tersebut tidak akan berfungsi, tentu saja. Tetapi kasus seperti itu tidak mungkin. Akibatnya, kita dapat mengatakan bahwa BigInteger dan BigDecimal dapat mewakili angka dengan ukuran yang hampir tidak terbatas. Untuk apa kelas-kelas ini digunakan? Pertama-tama, untuk perhitungan dengan persyaratan akurasi yang sangat ketat. Misalnya, kehidupan manusia mungkin bergantung pada keakuratan perhitungan di beberapa program (misalnya perangkat lunak yang mengontrol pesawat terbang, roket, atau peralatan medis). Jadi jika tempat desimal ke-150 penting, maka BigDecimaladalah pilihan terbaik. Selain itu, objek kelas ini sering digunakan dalam dunia keuangan, di mana perhitungan yang akurat dari nilai terkecil sekalipun juga sangat penting. Bagaimana Anda bekerja dengan objek BigInteger dan BigDecimal dan apakah Anda perlu mengetahuinya? Objek dari kelas-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);
   }
}
Meneruskan string ke konstruktor hanyalah salah satu opsi yang memungkinkan. Di sini kami menggunakan string, karena angka kami melebihi nilai maksimum untuk long dan double , dan kami memerlukan beberapa cara untuk menjelaskan kepada kompiler angka mana yang ingin kami buat :) Cukup dengan meneruskan angka 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111 ke konstruktor tidak akan berfungsi: Java akan mencoba menjejalkan nomor yang diteruskan ke salah satu tipe data primitif, tetapi tidak cocok dengan salah satunya. Itu sebabnya menggunakan string untuk melewati nomor yang diinginkan adalah pilihan yang baik. Kedua kelas dapat secara otomatis mengekstrak nilai numerik dari string yang diteruskan. Poin penting lainnya yang perlu diingat saat bekerja dengan kelas bilangan besar adalah bahwa objeknya tidak dapat diubah ( Immutable ). Anda sudah familiar dengan immutability berkat pengalaman Anda dengan class String dan class wrapper untuk tipe 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);

   }
}
Keluaran konsol:

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 
Seperti yang Anda harapkan, nomor kami tidak berubah. Untuk melakukan operasi penjumlahan, Anda harus membuat objek baru 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);

   }
}
Keluaran konsol:

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Lihat, sekarang semuanya berfungsi sebagaimana mestinya :) Omong-omong, apakah Anda memperhatikan betapa tidak biasa tampilan operasi penjumlahan?

BigInteger result = integer.add(BigInteger.valueOf(33333333));
Ini adalah poin penting lainnya. Kelas angka besar tidak menggunakan operator + - * /. Sebaliknya, mereka menyediakan satu set metode. Mari berkenalan dengan yang utama (seperti biasa, Anda dapat menemukan daftar lengkap metode dalam dokumentasi Oracle: di sini dan di sini ).
  1. metode untuk operasi aritmatika: add() , pengurangan() , perkalian() , pembagian() . Metode ini digunakan untuk melakukan penjumlahan, pengurangan, perkalian dan pembagian, masing-masing.

  2. doubleValue() , intValue() , floatValue() , longValue() , dll. digunakan untuk mengubah bilangan besar menjadi salah satu tipe primitif Java. Berhati-hatilah saat menggunakan metode ini. Jangan lupakan perbedaan ukuran 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);
    
       }
    }
    

    Keluaran konsol:

    
    8198552921648689607
    
  3. min() dan max() membiarkan Anda menemukan nilai minimum dan maksimum dari dua angka besar.
    Perhatikan bahwa metode ini tidak statis!

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

    Keluaran konsol:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
    

Perilaku pembulatan BigDecimal

Topik ini memiliki bagian tersendiri, karena membulatkan angka besar dan mengonfigurasi perilaku pembulatan tidak sesederhana itu. Anda dapat menggunakan metode setScale() untuk menyetel jumlah tempat desimal untuk BigDecimal . Misalnya, kita ingin angka 111.5555555555 memiliki tiga digit setelah titik desimal. Namun, kita tidak dapat mencapai apa yang kita inginkan dengan meneruskan angka 3 sebagai argumen ke metode setScale() . Seperti disebutkan di atas, BigDecimaladalah untuk merepresentasikan angka dengan persyaratan ketat pada presisi komputasi. Dalam bentuknya saat ini, angka kita memiliki 10 digit setelah titik desimal. Kami ingin membuang 7 di antaranya dan hanya menyimpan 3. Oleh karena itu, selain angka 3, kami harus melewati mode pembulatan. BigDecimal memiliki total 8 mode pembulatan. Itu banyak! Tetapi jika Anda benar-benar perlu menyempurnakan ketepatan perhitungan Anda, Anda akan memiliki semua yang Anda butuhkan. Nah, berikut adalah 8 mode pembulatan yang ditawarkan oleh BigDecimal :
  1. ROUND_CEILING — pembulatan ke atas

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

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

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

  4. ROUND_HALF_UP — pembulatan ke atas jika angka setelah titik desimal >= 0,5

    
    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
    
  5. ROUND_HALF_DOWN — membulatkan ke atas jika angka setelah titik desimal > 0,5

    
    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
    
  6. ROUND_HALF_EVEN — pembulatan bergantung pada angka di sebelah kiri titik desimal. Jika angka di sebelah kiri genap, pembulatan akan ke bawah. Jika angka di sebelah kiri titik desimal ganjil, maka pembulatan akan ke atas.

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

    Angka di sebelah kiri tempat desimal adalah 2 (genap). Angka dibulatkan ke bawah. Kami ingin 0 tempat desimal, jadi hasilnya adalah 2.

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

    Angka di sebelah kiri titik desimal adalah 3 (ganjil). Jumlahnya dibulatkan. Kami ingin 0 tempat desimal, jadi hasilnya adalah 4.

  7. ROUND_UNNECCESSARY — Mode ini digunakan saat Anda harus meneruskan mode pembulatan ke suatu metode, tetapi angkanya tidak perlu dibulatkan. Jika Anda mencoba membulatkan angka dengan set mode ROUND_UNNECCESSARY, ArithmeticException akan dilempar.

    
    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
    
  8. ROUND_UP — pembulatan dari nol.

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

Membandingkan angka besar

Ini juga penting. Anda akan ingat bahwa kami menggunakan metode equals() adalah membandingkan objek di Java. Implementasinya disediakan oleh bahasa itu sendiri (untuk kelas Java standar) atau diganti oleh programmer. Namun dalam kasus objek BigDecimal , penggunaan metode equals() untuk perbandingan tidak disarankan. Ini karena metode BigDecimal.equals() mengembalikan true hanya jika 2 angka memiliki nilai dan skala yang sama: Mari bandingkan perilaku metode 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));
      
   }
}
Keluaran konsol:

true 
false
Seperti yang Anda lihat, untuk BigDecimal , angka 1,5 dan 1,50 ternyata tidak sama! Ini justru karena kekhususan penerapan metode equals() di kelas BigDecimal . Untuk perbandingan dua objek BigDecimal yang lebih akurat , lebih baik menggunakan metode 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));

   }
}
Keluaran konsol:

0
Metode compareTo() mengembalikan 0, yang berarti 1,5 dan 1,50 sama. Dan inilah hasil yang kami harapkan! :) Itu mengakhiri pelajaran kita hari ini. Sekarang saatnya untuk kembali ke tugas! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION