JavaRush /Blogue Java /Random-PT /BigInteger e BigDecimal

BigInteger e BigDecimal

Publicado no grupo Random-PT
Em Java, um aplicativo é composto de classes e as classes são compostas de métodos e variáveis. As variáveis, por sua vez, são divididas em primitivas e de referência. BigInteger e BigDecimal - 1Existem 8 tipos de variáveis ​​em Java e, excluindo booleane char, elas são divididas nos seguintes tipos:
  • inteiros: byte, short, inte long;
  • ponto flutuante (também chamados de números reais): floate double.
Dentro desses pequenos grupos, as diferenças existem apenas na faixa de valores que podem ser contidos (e, consequentemente, o espaço ocupado por tal variável varia). O maior dos tipos inteiros é long, com um intervalo de -9223372036854775808 a 9223372036854775807. Dos números de ponto flutuante, , doublecom um intervalo de 1,7e-308 a 1,7e+308. Você pode ler mais sobre números reais neste artigo . Mas e se precisarmos armazenar números que excedam o intervalo aceitável? Neste caso, precisaremos BigIntegerde e BigDecimal.

BigInteger em Java

A classe Java BigIntegeré usada como um análogo para valores inteiros de comprimento arbitrário que não possuem o limite de comprimento de 64 bits. Além disso, é descendente da classe Number, como wrappers padrão para tipos simples numéricos - Integer, Long, Bytee Doubleassim por diante - portanto, possui implementações de métodos que levam a tipos simples:
BigInteger value = new BigInteger("32145");

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

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

double doubleValue = value.doubleValue();//32145.0
Imediatamente vemos a criação de tal objeto BigIntegercom nosso valor sendo passado para o construtor, mas em formato string. Vale ressaltar que ele conta com mais de um designer, mas para todas as ocasiões. Se os tipos primitivos não acomodarem a quantidade total de dados de BigInteger, os dados serão truncados para o intervalo desse tipo primitivo. Mas, ao mesmo tempo, existem análogos desses métodos ( intValueExact(), longValueExact()etc.), com a única diferença de que se o tipo simples para o qual a conversão está ocorrendo não acomodar o intervalo de dados, uma ArithmeticException será lançada .

Constantes BigInteger

Para uso interno, a classe possui constantes:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Estes são objetos constantes BigIntegercom valores, respectivamente 0, 1e 10.

Métodos BigInteger

Uma das principais características desta classe é que ela está repleta de métodos que implementam operações aritméticas padrão em Java. Por exemplo:
  • operações de soma:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • operações de multiplicação:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • operações de encontrar o resto ao dividir um número por outro:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • obtendo o valor absoluto de um número (ou seja, módulo, sem sinal):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
Existem também métodos para operações mais complexas (específicas):
  • operações com cálculo mod :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
Existem diversas variações desta função:
  • obtendo um número aleatório e especificando o número de bits que o valor resultante usará:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • operações de deslocamento bit a bit (este >> n)

    Deslocar para a esquerda:

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

    Deslocar para a direita:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
Claro, é melhor consultar a lista completa de métodos na documentação . BigInteger e BigDecimal - 2

BigDecimal em Java

Quando precisamos de um número real de comprimento arbitrário, a classe Java é usada - BigDecimal. Via de regra, é utilizado para trabalhar com finanças ao invés de double, pois oferece mais opções de customização. Assim como e BigInteger, BigDecimalé descendente de uma classe Numbere possui métodos que retornam o valor de um objeto como um tipo primitivo específico:
BigDecimal value = new BigDecimal(35563.3);

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

double doubleValue = value.doubleValue();//35563.3
Como podemos ver ao reduzir para long, resta apenas a parte inteira e as casas decimais são descartadas.

Construtores BigDecimal

Vamos dar uma olhada mais de perto nos construtores BigDecimal, já que a classe possui uma seleção muito mais ampla deles. Existem construtores que permitem definir o valor de um objeto de diferentes maneiras (passando int, long, doublee Stringaté BigInteger), e há aqueles que permitem isso. defina as configurações do objeto criado (métodos de arredondamento, número de casas decimais):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Tudo está claro aqui, definimos diretamente o valor e o número de casas decimais que queremos ver.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
Os resultados deste construtor podem ser bastante imprevisíveis, porque estamos especificando um double, que por natureza é um tipo muito ambíguo. Portanto, geralmente é recomendado usar em um construtor String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
Definimos double, mas ao mesmo tempo também definimos um parâmetro que descreve a regra de arredondamento (que contém o número de casas decimais e o algoritmo de arredondamento).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
Definimos um array de caracteres de qual elemento obtemos os valores do objeto e quantos desses elementos obtemos.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Pegamos um objeto já existente BigIntegere definimos o número de casas decimais.

Métodos BigDecimais

A classe BigDecimaltambém contém métodos para diversas operações aritméticas, mas BigIntegernão possui métodos para trabalhar com bits, como . Mesmo assim, a principal característica BigDecimalé a flexibilidade em trabalhar com números de ponto flutuante. Vejamos algumas técnicas que nos dão o poder de dominar os números reais:
  • obtemos a precisão (número de números):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • defina o número de casas decimais e a regra de arredondamento:

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

    A seguir veremos mais de perto as constantes para definir regras de arredondamento.

  • dividir BigDecimalpor outro BigDecimal, indicando o número necessário de casas decimais e a regra de arredondamento:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • mover uma vírgula para a direita/esquerda por um certo número de casas:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • aparar zeros à direita:

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

    Se tivermos todos os zeros na parte real e também houver zeros na parte inteira (ou não tivermos nenhuma casa decimal), então:

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

Regras de arredondamento BigDecimal

Para definir regras de arredondamento, BigDecimalpodemos ver constantes especiais que descrevem algoritmos de arredondamento: ROUND_UP- arredondamento de zero, arredondamento para a parte real:
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— arredondamento para zero, ou seja, truncamento da parte real:
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— arredondando para infinito positivo. Ou seja, se nosso número for positivo, então -> ROUND_UP, se negativo, então ->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- arredondamento para infinito negativo, ou seja, se nosso número for positivo, então -> ROUND_DOWN, se negativo, então ->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
Para o valor em consideração, consideraremos este número mais próximo com casa decimal truncada como o vizinho mais próximo do número em consideração. Por exemplo, 2,43 estará mais próximo de 2,4 do que 2,5, mas 2,48 estará mais próximo de 2,5. ROUND_HALF_DOWN— arredondando para o “vizinho mais próximo”. Se ambos os vizinhos estiverem equidistantes de um valor específico, então será realizado o arredondamento para zero. Equidistante é, por exemplo, quando o número que está sendo arredondado é 5 e está à mesma distância de 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— modo de arredondamento para o “vizinho mais próximo”. Se ambos os vizinhos forem equidistantes, o arredondamento é feito (este é o mesmo arredondamento que aprendemos na escola):
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— arredondamento para o “vizinho mais próximo” se ambos os vizinhos não forem equidistantes. Neste caso, se o número a ser arredondado for precedido de um número ímpar, ele é arredondado para cima, e se for par, é arredondado para baixo:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
Obtemos esse resultado porque ao arredondar, 5 olha para o número 2 anterior, e vendo que é par, arredonda para baixo. Mas se:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
Esse arredondamento aumenta, pois o último 5 olha o valor anterior e vê um número ímpar. Como resultado, o número é arredondado para 6, após o qual o próximo 6 também é arredondado. Mas o seis não olha mais para o número da esquerda, pois o número está claramente mais próximo para cima e, como resultado, os 2 últimos são aumentados em 1. ROUND_UNNECESSARY- usado para verificar se o número não precisa ser arredondado. Ou seja, verificamos se o número possui o número necessário de casas decimais:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Está tudo bem aqui, o valor tem dois dígitos e verificamos que existem apenas dois dígitos após a vírgula. Mas se:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Então obtemos - ArithmeticException, pois o valor que está sendo testado excede o número especificado de casas decimais. Mas se verificarmos duas casas decimais, mas na verdade existe uma, então a exceção não será lançada e os dígitos que faltam serão simplesmente complementados com zeros:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
Também gostaria de observar que y tem BigDecimalconstantes semelhantes às constantes BigInteger ZEROe ONE. TENAqui está um link para a documentação . E por último: como você provavelmente notou, ao realizar operações com objetos BigIntegere BigDecimal, não alteramos os antigos, mas sempre obtemos novos. Isso nos diz que eles são immutable, isto é, imutáveis ​​após sua criação, assim como String. Em outras palavras, todos os seus métodos não podem alterar o estado interno do objeto; no máximo, eles podem retornar um novo objeto com os parâmetros especificados pela função que estamos usando.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION