JavaRush /Blog Java /Random-MS /BigInteger dan BigDecimal

BigInteger dan BigDecimal

Diterbitkan dalam kumpulan
Di Java, aplikasi terdiri daripada kelas, dan kelas terdiri daripada kaedah dan pembolehubah. Pembolehubah pula dibahagikan kepada primitif dan rujukan. BigInteger dan BigDecimal - 1Terdapat 8 jenis pembolehubah dalam Java dan, tidak termasuk booleandan char, ia dibahagikan kepada jenis berikut:
  • integer: byte, short, intdan long;
  • titik terapung (juga dipanggil nombor nyata): floatdan double.
Dalam kumpulan kecil ini, perbezaan hanya wujud dalam julat nilai yang boleh terkandung (dan, oleh itu, ruang yang diduduki pembolehubah sedemikian berbeza-beza). Jenis integer terbesar ialah long, dengan julat daripada -9223372036854775808 hingga 9223372036854775807. Daripada nombor titik terapung, double, dengan julat 1.7e-308 hingga 1.7e+308. Anda boleh membaca lebih lanjut mengenai nombor nyata dalam artikel ini . Tetapi bagaimana jika kita perlu menyimpan nombor yang melebihi julat yang boleh diterima? Dalam kes ini, kita akan memerlukan BigIntegerdan BigDecimal.

BigInteger dalam Java

Kelas Java BigIntegerdigunakan sebagai analog kepada nilai integer panjang sewenang-wenang yang tidak mempunyai had panjang 64-bit. Selain itu, ia adalah keturunan class Number, seperti pembalut standard untuk jenis ringkas berangka - Integer, Long, Bytedan Doubleseterusnya - oleh itu ia mempunyai pelaksanaan kaedah yang membawa kepada jenis ringkas:
BigInteger value = new BigInteger("32145");

int intValue = value.intValue();//32145

long longValue = value.longValue();//32145

double doubleValue = value.doubleValue();//32145.0
Serta-merta kita melihat penciptaan objek sedemikian BigIntegerdengan nilai kita dihantar kepada pembina, tetapi dalam format rentetan. Perlu diingat bahawa dia mempunyai lebih daripada satu pereka, tetapi untuk semua kesempatan. Jika jenis primitif tidak menampung jumlah penuh data daripada BigInteger, data akan dipotong kepada julat jenis primitif tersebut. Tetapi pada masa yang sama, terdapat analog kaedah ini ( intValueExact(), longValueExact()dsb.), dengan satu-satunya perbezaan ialah jika jenis mudah yang penukaran berlaku tidak menampung julat data, ArithmeticException dilemparkan .

Pemalar BigInteger

Untuk kegunaan dalaman, kelas mempunyai pemalar:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Ini adalah objek malar BigIntegerdengan nilai, masing-masing, 0, 1dan 10.

Kaedah BigInteger

Salah satu ciri utama kelas ini ialah ia penuh dengan kaedah yang melaksanakan operasi aritmetik standard di Jawa. Sebagai contoh:
  • operasi penjumlahan:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • operasi darab:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • operasi mencari baki apabila membahagi satu nombor dengan yang lain:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • mendapatkan nilai mutlak nombor (iaitu, modulo, tidak ditandatangani):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
Terdapat juga kaedah untuk operasi yang lebih kompleks (khusus):
  • operasi dengan pengiraan mod :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
Terdapat beberapa variasi fungsi ini:
  • mendapatkan nombor rawak dan menentukan bilangan bit yang akan digunakan oleh nilai yang terhasil:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • operasi anjakan bitwise(ini >> n)

    Beralih ke kiri:

    BigInteger firstValue = new BigInteger("5");
    BigInteger firstResultValue = firstValue.shiftLeft(3);//40

    Beralih ke kanan:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
Sudah tentu, adalah lebih baik untuk melihat senarai penuh kaedah dalam dokumentasi . Integer Besar dan Perpuluhan Besar - 2

BigDecimal dalam Java

Apabila kita memerlukan bilangan sebenar panjang sewenang-wenangnya, kelas Java digunakan - BigDecimal. Sebagai peraturan, ia digunakan untuk bekerja dengan kewangan dan bukannya double, kerana ia memberikan lebih banyak pilihan penyesuaian. Suka dan BigInteger, BigDecimalialah keturunan kelas Numberdan mempunyai kaedah yang mengembalikan nilai objek sebagai jenis primitif tertentu:
BigDecimal value = new BigDecimal(35563.3);

long longValue = value.longValue();//35563

double doubleValue = value.doubleValue();//35563.3
Seperti yang kita dapat lihat apabila dikurangkan kepada long, hanya bahagian integer yang tinggal, dan tempat perpuluhan dibuang.

Pembina BigDecimal

Kami akan melihat dengan lebih dekat pada constructors BigDecimal, kerana kelas mempunyai pilihan yang lebih luas daripada mereka. Terdapat pembina yang membolehkan anda menetapkan nilai objek dengan cara yang berbeza (dengan lulus int, long, double, Stringdan genap BigInteger), dan ada yang membenarkannya. tetapkan tetapan objek yang dibuat (kaedah pembundaran, bilangan tempat perpuluhan):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Semuanya jelas di sini, kami terus menetapkan nilai dan bilangan tempat perpuluhan yang ingin kami lihat.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
Keputusan pembina ini boleh menjadi agak tidak dapat diramalkan, kerana kami menentukan dua kali ganda, yang oleh sifatnya adalah jenis yang sangat samar-samar. Oleh itu, secara amnya disyorkan untuk digunakan dalam pembina String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
Kami menetapkan double, tetapi pada masa yang sama kami juga menetapkan parameter yang menerangkan peraturan pembundaran (yang mengandungi bilangan tempat perpuluhan dan algoritma untuk pembundaran).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
Kami menetapkan tatasusunan aksara daripada elemen mana kami mengambil nilai untuk objek dan berapa banyak elemen ini yang kami ambil.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Kami mengambil objek yang sudah sedia ada BigInteger, tetapkan bilangan tempat perpuluhan.

Kaedah BigDecimal

Kelas BigDecimaljuga mengandungi kaedah untuk pelbagai operasi aritmetik, tetapi BigIntegeria tidak mempunyai kaedah untuk bekerja dengan bit, seperti . Namun begitu, ciri utama BigDecimalialah fleksibiliti dalam bekerja dengan nombor titik terapung. Mari kita lihat beberapa teknik yang memberi kita kuasa untuk menguasai nombor nyata:
  • kita mendapat ketepatan (bilangan nombor):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • tetapkan bilangan tempat perpuluhan dan peraturan pembundaran:

    BigDecimal firstValue = new BigDecimal(3445.544445);
    
    BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545

    Di bawah ini kita akan melihat dengan lebih dekat pemalar untuk menetapkan peraturan pembundaran.

  • bahagikan BigDecimaldengan yang lain BigDecimal, sambil menunjukkan bilangan tempat perpuluhan yang diperlukan dan peraturan pembundaran:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • menggerakkan titik perpuluhan ke kanan/kiri dengan bilangan tempat tertentu:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • potong sifar mengekor:

    BigDecimal value = new BigDecimal("45056.5000");
    BigDecimal result = value.stripTrailingZeros();//45056.5

    Jika kita mempunyai semua sifar di bahagian sebenar dan terdapat juga sifar di seluruh bahagian (atau kita tidak mempunyai tempat perpuluhan sama sekali), maka:

    BigDecimal value = new BigDecimal("450000.000");
    BigDecimal result = value.stripTrailingZeros();//4.5E+5

Peraturan pembundaran BigDecimal

Untuk menetapkan peraturan pembundaran, di dalamnya BigDecimalkita boleh melihat pemalar khas yang menerangkan algoritma pembundaran: ROUND_UP- pembundaran dari sifar, pembundaran ke arah bahagian sebenar:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN— membundarkan kepada sifar, iaitu, pemangkasan bahagian sebenar:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_DOWN  );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN  );//-2.6
ROUND_CEILING— pembundaran kepada infiniti positif. Iaitu, jika nombor kita positif, maka -> ROUND_UP, jika negatif, maka ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR- pembundaran kepada infiniti negatif, iaitu, jika nombor kita positif, maka -> ROUND_DOWN, jika negatif, maka ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
Untuk nilai yang sedang dipertimbangkan, kami akan menganggap nombor terdekat ini dengan tempat perpuluhan terpotong sebagai jiran terdekat nombor yang sedang dipertimbangkan. Sebagai contoh, 2.43 akan lebih hampir kepada 2.4 daripada 2.5, tetapi 2.48 akan lebih hampir kepada 2.5. ROUND_HALF_DOWN— membundarkan kepada "jiran terdekat". Jika kedua-dua jiran adalah sama jarak dari nilai tertentu, maka pusingan kepada sifar dilakukan. Jarak sama ialah, sebagai contoh, apabila nombor yang dibundarkan ialah 5, dan ia adalah jarak yang sama dari 0 dan 10):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP— mod untuk membulatkan ke arah "jiran terdekat". Jika kedua-dua jiran adalah sama, pembundaran dilakukan (ini adalah pembulatan yang sama yang kami ajar di sekolah):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.6
ROUND_HALF_EVEN— membundarkan kepada "jiran terdekat" jika kedua-dua jiran tidak sama jarak. Dalam kes ini, jika nombor yang dibundarkan didahului oleh nombor ganjil, ia dibundarkan ke atas, dan jika ia genap, ia dibundarkan ke bawah:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
Kami mendapat keputusan ini kerana apabila membundarkan, 5 melihat nombor 2 sebelumnya, dan melihat bahawa ia adalah genap, membundarkan ke bawah. Tetapi kalau:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
Pembundaran itu meningkat, kerana 5 terakhir melihat nilai sebelumnya dan melihat nombor ganjil. Akibatnya, nombor dibundarkan kepada 6, selepas itu 6 seterusnya juga dibundarkan. Tetapi enam tidak lagi melihat nombor di sebelah kiri, kerana nombor itu jelas lebih dekat ke atas, dan akibatnya 2 terakhir ditambah sebanyak 1. ROUND_UNNECESSARY- digunakan untuk memeriksa bahawa nombor itu tidak perlu dibundarkan. Iaitu, kami menyemak sama ada nombor itu mempunyai bilangan tempat perpuluhan yang diperlukan:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Semuanya baik-baik saja di sini, nilainya mempunyai dua digit dan kami menyemak bahawa terdapat hanya dua digit selepas titik perpuluhan. Tetapi kalau:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Kemudian kita dapat - ArithmeticException, kerana nilai yang diuji melebihi bilangan tempat perpuluhan yang ditentukan. Tetapi jika kita menyemak dua tempat perpuluhan, tetapi sebenarnya ada satu di sana, maka pengecualian tidak akan dibuang, dan digit yang hilang hanya ditambah dengan sifar:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
Saya juga ingin ambil perhatian bahawa y BigDecimalmempunyai pemalar yang serupa dengan pemalar BigInteger ZERO, ONEdan TEN. Berikut adalah pautan kepada dokumentasi . Dan akhirnya: seperti yang mungkin anda perhatikan, apabila melakukan operasi dengan objek BigIntegerdan BigDecimal, kami tidak menukar yang lama, tetapi sentiasa mendapat yang baharu. Ini memberitahu kita bahawa mereka adalah immutable, iaitu, tidak berubah selepas penciptaan mereka, sama seperti String. Dalam erti kata lain, semua kaedah mereka tidak boleh mengubah keadaan dalaman objek; paling banyak, mereka boleh mengembalikan objek baharu dengan parameter yang ditentukan oleh fungsi yang kami gunakan.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION