JavaRush /Java Blog /Random-IT /BigInteger e BigDecimal

BigInteger e BigDecimal

Pubblicato nel gruppo Random-IT
In Java, un'applicazione è composta da classi e le classi sono costituite da metodi e variabili. Le variabili, a loro volta, si dividono in primitive e di riferimento. BigInteger e BigDecimal - 1Esistono 8 tipi di variabili in Java e, escludendo booleane char, si dividono nelle seguenti tipologie:
  • numeri interi: byte, short, inte long;
  • virgola mobile (chiamati anche numeri reali): floate double.
All'interno di questi piccoli gruppi, le differenze esistono solo nell'intervallo di valori che possono essere contenuti (e, di conseguenza, varia lo spazio occupato da tale variabile). Il più grande dei tipi interi è long, con un intervallo compreso tra -9223372036854775808 e 9223372036854775807. Tra i numeri in virgola mobile, double, con un intervallo compreso tra 1,7e-308 e 1,7e+308. Puoi leggere di più sui numeri reali in questo articolo . Ma cosa succede se dobbiamo memorizzare numeri maggiori dell’intervallo accettabile? In questo caso, avremo bisogno BigIntegerdi e BigDecimal.

BigInteger in Java

La classe Java BigIntegerviene utilizzata come analogo ai valori interi di lunghezza arbitraria che non hanno il limite di 64 bit di long. Inoltre, è un discendente della classe Number, come i wrapper standard per i tipi numerici semplici - Integer, Long, Byte, Doublee così via - quindi ha implementazioni di metodi che portano a tipi semplici:
BigInteger value = new BigInteger("32145");

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

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

double doubleValue = value.doubleValue();//32145.0
Immediatamente vediamo la creazione di un oggetto del genere BigIntegercon il nostro valore passato al costruttore, ma in formato stringa. Vale la pena notare che ha più di un designer, ma per tutte le occasioni. Se i tipi primitivi non supportano l'intera quantità di dati da BigInteger, i dati verranno troncati all'intervallo di quel tipo primitivo. Ma allo stesso tempo, ci sono analoghi di questi metodi ( intValueExact(), longValueExact()ecc.), con l'unica differenza che se il tipo semplice in cui avviene la conversione non soddisfa l'intervallo di dati, viene lanciata un'ArithmeticException .

Costanti BigInteger

Per uso interno, la classe ha costanti:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Questi sono oggetti costanti BigIntegercon valori, rispettivamente 0, 1e 10.

Metodi BigInteger

Una delle caratteristiche principali di questa classe è che è ricca di metodi che implementano operazioni aritmetiche standard in Java. Per esempio:
  • operazioni di somma:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • operazioni di moltiplicazione:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • operazioni per trovare il resto della divisione di un numero per un altro:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • ottenere il valore assoluto di un numero (ovvero modulo, senza segno):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
Esistono anche metodi per operazioni più complesse (specifiche):
  • operazioni con calcolo mod :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
Esistono diverse varianti di questa funzione:
  • ottenendo un numero casuale e specificando il numero di bit che utilizzerà il valore risultante:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • operazioni di spostamento bit a bit (questo >> n)

    Spostamento a sinistra:

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

    Sposta a destra:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
Naturalmente è meglio consultare l'elenco completo dei metodi nella documentazione . BigInteger e BigDecimal - 2

BigDecimal in Java

Quando abbiamo bisogno di un numero reale di lunghezza arbitraria, viene utilizzata la classe Java - BigDecimal. Di norma, viene utilizzato per lavorare con le finanze anziché con double, poiché offre più opzioni di personalizzazione. Come and BigInteger, BigDecimalè un discendente di una classe Numbere dispone di metodi che restituiscono il valore di un oggetto come un tipo primitivo specifico:
BigDecimal value = new BigDecimal(35563.3);

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

double doubleValue = value.doubleValue();//35563.3
Come possiamo vedere riducendo a long, rimane solo la parte intera e le cifre decimali vengono scartate.

Costruttori BigDecimal

Daremo un'occhiata più da vicino ai costruttori BigDecimal, poiché la classe ne ha una selezione molto più ampia. Esistono costruttori che consentono di impostare il valore di un oggetto in diversi modi (passando int, long, doublee Stringanche BigInteger), e ci sono anche quelli che lo consentono. definire le impostazioni dell'oggetto creato (metodi di arrotondamento, numero di cifre decimali):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Qui è tutto chiaro, impostiamo direttamente il valore e il numero di cifre decimali che vogliamo vedere.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
I risultati di questo costruttore possono essere piuttosto imprevedibili, perché stiamo specificando double, che per sua natura è un tipo molto ambiguo. Pertanto, si consiglia generalmente di utilizzarlo in un costruttore String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
Impostiamo double, ma allo stesso tempo impostiamo anche un parametro che descrive la regola di arrotondamento (che contiene il numero di cifre decimali e l'algoritmo per l'arrotondamento).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
Impostiamo un array di caratteri da quale elemento prendiamo i valori per l'oggetto e quanti di questi elementi prendiamo.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Prendiamo un oggetto già esistente BigInteger, impostiamo il numero di cifre decimali.

Metodi BigDecimal

La classe BigDecimalcontiene anche metodi per varie operazioni aritmetiche, ma BigIntegernon dispone di metodi per lavorare con i bit, come . Tuttavia, la caratteristica principale BigDecimalè la flessibilità nel lavorare con numeri in virgola mobile. Diamo un'occhiata ad alcune tecniche che ci danno il potere di padroneggiare i numeri reali:
  • otteniamo la precisione (numero di numeri):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • imposta il numero di cifre decimali e la regola di arrotondamento:

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

    Di seguito esamineremo più da vicino le costanti per l'impostazione delle regole di arrotondamento.

  • dividere BigDecimalper un altro BigDecimal, indicando il numero richiesto di cifre decimali e la regola di arrotondamento:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • spostando un punto decimale a destra/sinistra di un certo numero di posizioni:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • tagliare gli zeri finali:

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

    Se abbiamo tutti zeri nella parte reale e ci sono anche zeri nella parte intera (o non abbiamo alcuna cifra decimale), allora:

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

Regole di arrotondamento BigDecimal

Per impostare le regole di arrotondamento, all'interno BigDecimalpossiamo vedere apposite costanti che descrivono gli algoritmi di arrotondamento: ROUND_UP- arrotondamento da zero, arrotondamento verso la parte reale:
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— arrotondamento a zero, cioè troncamento della parte reale:
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— arrotondamento all'infinito positivo. Cioè, se il nostro numero è positivo, allora -> ROUND_UP, se negativo, allora ->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- arrotondamento all'infinito negativo, cioè se il nostro numero è positivo, allora -> ROUND_DOWN, se negativo, allora ->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
Per il valore in esame, considereremo questo numero più vicino con una cifra decimale troncata come il vicino più prossimo del numero in questione. Ad esempio, 2,43 sarà più vicino a 2,4 che a 2,5, ma 2,48 sarà più vicino a 2,5. ROUND_HALF_DOWN— arrotondamento al “vicino più vicino”. Se entrambi i vicini sono equidistanti da un particolare valore, viene eseguito l'arrotondamento a zero. Equidistante è, ad esempio, quando il numero da arrotondare è 5, ed è alla stessa distanza da 0 e 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— modalità di arrotondamento verso il “vicino più vicino”. Se entrambi i vicini sono equidistanti si esegue l'arrotondamento per eccesso (è lo stesso arrotondamento che ci hanno insegnato a scuola):
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— arrotondamento al “vicino più vicino” se entrambi i vicini non sono equidistanti. In questo caso, se il numero da arrotondare è preceduto da un numero dispari, viene arrotondato per eccesso, se è pari, viene arrotondato per difetto:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
Otteniamo questo risultato perché durante l'arrotondamento, 5 guarda il numero precedente 2 e, vedendo che è pari, arrotonda per difetto. Ma se:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
L'arrotondamento aumenta, poiché gli ultimi 5 guardano il valore precedente e vedono un numero dispari. Di conseguenza, il numero viene arrotondato a 6, dopodiché viene arrotondato anche il 6 successivo. Ma il sei non guarda più il numero a sinistra, poiché il numero è chiaramente più vicino verso l'alto, e di conseguenza l'ultimo 2 viene aumentato di 1. ROUND_UNNECESSARY- serve per verificare che il numero non debba essere arrotondato. Controlliamo cioè che il numero abbia il numero di cifre decimali richiesto:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Qui va tutto bene, il valore ha due cifre e controlliamo che ci siano solo due cifre dopo la virgola. Ma se:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Quindi otteniamo - ArithmeticException, poiché il valore da testare supera il numero specificato di cifre decimali. Ma se controlliamo due cifre decimali, ma in realtà ce n'è una, l'eccezione non verrà generata e le cifre mancanti verranno semplicemente integrate con zeri:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
Vorrei anche notare che y BigDecimalha costanti simili alle costanti BigInteger ZERO, ONEe TEN. Ecco un collegamento alla documentazione . E infine: come probabilmente avrai notato, quando eseguiamo operazioni con oggetti BigIntegere BigDecimal, non cambiamo quelli vecchi, ma ne otteniamo sempre di nuovi. Questo ci dice che sono immutable, cioè, immutabili dopo la loro creazione, proprio come String. In altre parole, tutti i loro metodi non possono modificare lo stato interno dell'oggetto; al massimo possono restituire un nuovo oggetto con i parametri specificati dalla funzione che stiamo utilizzando.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION