Tipo primitivo | Tamanho na memória | Faixa de valores |
---|---|---|
byte | 8 bits | -128 a 127 |
curto | 16 bits | para -32768 a 32767 |
Caracteres | 16 bits | de 0 a 65536 |
interno | 32 bits | de -2147483648 a 2147483647 |
longo | 64 bits | de -9223372036854775808 a 9223372036854775807 |
flutuador | 32 bits | de (2 elevado a -149) a ((2-2 elevado a -23)*2 elevado a 127) |
dobro | 64 bits | de (-2 elevado a 63) a ((2 elevado a 63) - 1) |
boleano | 8 (quando usado em arrays), 32 (quando usado em não arrays) | verdadeiro ou falso |
BigInteger
é BigDecimal
praticamente ilimitado. Para que servem essas aulas? Em primeiro lugar, para cálculos com requisitos de precisão extremamente elevados. Existem, por exemplo, programas em que a vida humana pode depender da precisão dos cálculos (softwares para aviões e foguetes ou para equipamentos médicos). Portanto, mesmo que a 150ª casa decimal desempenhe um papel importante, BigDecimal
é a melhor escolha. Além disso, muitas vezes esses objetos são utilizados no mundo das finanças, onde a precisão dos cálculos até os menores valores também é extremamente importante. Como trabalhar com objetos BigInteger
e BigDecimal
o que é importante lembrar sobre eles? Os objetos dessas classes são criados assim:
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);
}
}
Passar uma string como parâmetro é apenas um dos construtores possíveis. Aqui usamos strings porque nossos números excedem os valores máximos long
e double
, e de alguma forma precisamos explicar ao compilador exatamente qual número queremos obter :) Basta passar o número 111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111 para o construtor 11111111111111111111111111111111111111111111111111111111111111111 não funcionará: Java tentará “encaixa” o número passado em um dos tipos de dados primitivos, mas não cabe em nenhum deles. Portanto, utilizar uma string para passar o número desejado é uma boa opção. Ambas as classes podem extrair automaticamente valores numéricos de strings passadas. Outro ponto importante a lembrar ao trabalhar com classes de grande número é que seus objetos são imutáveis ( Immutable
) . Você já conhece bem o princípio da imutabilidade através do exemplo de uma classe String
e classes wrapper para primitivas (Integer, Long e outras).
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);
}
}
Saída do console:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Nossos números não mudaram, como seria de esperar. Para que a operação de adição seja bem-sucedida, você deve criar um novo objeto e atribuir a ele o resultado da adição.
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);
}
}
Saída do console:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Agora tudo funciona como deveria :) A propósito, você notou como a operação de adição parece incomum?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Este é outro ponto importante. Classes de números grandes não usam os operadores +-*/ em suas operações, mas fornecem um conjunto de métodos. Vamos dar uma olhada nos principais (você pode, como sempre, encontrar uma lista completa de métodos na documentação do Oracle: aqui e aqui ).
-
métodos para realizar operações aritméticas:
add()
,subtract()
,multiply()
,divide()
. Usado para operações de adição, subtração, multiplicação e divisão, respectivamente. -
doubleValue()
,intValue()
,floatValue()
,longValue()
etc - Usado para converter um grande número em um tipo primitivo Java. Tenha cuidado ao usá-los e lembre-se da diferença de capacidade!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); } }
Saída do console:
8198552921648689607
-
min()
emax()
- permite encontrar o valor mínimo e máximo de dois números grandes passados.
Observação: os métodos não são estáticos!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)); } }
Saída do console:
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
Controle de arredondamento BigDecimal
Este tópico está incluído em uma seção separada, pois arredondar números grandes e ajustá-los não é uma coisa tão simples. Você pode definir o número de casas decimais para um númeroBigDecimal
usando o setScale()
. Por exemplo, queremos definir a precisão do número 111,5555555555 com três casas decimais. Porém, não conseguiremos passar o número 3 como argumento para o método setScale()
e assim resolver nosso problema. Conforme mencionado acima, BigDecimal
estes são números para cálculos com maior precisão. Em sua forma atual, nosso número possui 10 casas decimais. Queremos descartar 7 deles e deixar apenas 3. Portanto, além do número 3, devemos passar como parâmetro o modo de arredondamento . Existem 8 modos de arredondamento no total BigDecimal
. Bastante! Mas se precisar realmente ajustar a precisão dos cálculos no programa, você terá tudo o que precisa para isso. Então, aqui estão os 8 modos de arredondamento disponíveis em BigDecimal
:
-
ROUND_CEILING
- arredondamento para cima111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
-
ROUND_DOWN
- descarte de descarga111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
-
ROUND_FLOOR
- arredondando para baixo111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
-
ROUND_HALF_UP
— arredondamento se o número após a vírgula >= 0,50.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
-
ROUND_HALF_DOWN
— arredondamento se o número após a vírgula > 0,50.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
-
ROUND_HALF_EVEN
— o arredondamento dependerá do número à esquerda da vírgula. Se o número à esquerda for par, o arredondamento será feito para baixo. Se o número à esquerda da vírgula for ímpar, será arredondado para cima.2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
O número à esquerda da vírgula – 2 – é par. O arredondamento ocorre para baixo. Como exigimos 0 casas decimais, o resultado será 2.
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
O número à esquerda da vírgula – 3 – é ímpar. O arredondamento ocorre para cima. Como exigimos 0 casas decimais, o resultado será 4.
-
ROUND_UNNECCESSARY
— utilizado nos casos em que o modo de arredondamento precisa ser passado para algum método, mas o número não necessita de arredondamento. Se você tentar arredondar um número quando o modo ROUND_UNNECCESSARY estiver definido, uma ArithmeticException será lançada.3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
-
ROUND_UP
- arredondamento para cima.111.5551 -> setScale(3, ROUND_UP) -> 111.556
Comparação de grandes números
Esta questão também é importante. Você já lembra que o método serve para comparar objetos em Javaequals()
. Ele é fornecido pela própria linguagem (no caso das classes internas do Java) ou substituído pelo programador. Mas no caso de objetos de classe, não é recomendado BigDecimal
usar o método equals()
para comparação. A razão para isso é que o BigDecimal.equals()
método de dois números retorna verdadeiro apenas se os dois números tiverem o mesmo valor e escala : Vamos comparar o comportamento dos métodos equals()
y Double
e y 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));
}
}
Saída do console:
true
false
Como você pode ver, os números 1,5 e 1,50 no caso de c BigDecimal
revelaram-se desiguais! Isso aconteceu justamente por causa das especificidades do método equals()
na classe BigDecimal
. Para uma comparação mais correta dos dois, BigDecimal
é melhor usar o método 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));
}
}
Saída do console:
0
O método compareTo()
retornou 0, o que significa igual a 1,5 e 1,50. Este é o resultado com que estávamos contando! :) Isso conclui nossa lição de hoje. É hora de voltar às tarefas! :)
GO TO FULL VERSION