Pergunta

Recentemente eu tentei compreender o uso das o java.matemática.MathContext mas não conseguiu entender corretamente.Ele é usado para arredondamento java.math.BigDecimal.Se sim, por que não arredondar os dígitos decimais mas mesmo mantissa parte.

A partir da API do google docs, eu vim a saber que ele segue o padrão especificado no ANSI X3.274-1996 e ANSI X3.274-1996/AM 1-2000 especificações mas eu não levá-los para leitura on-line.

Por favor, deixe-me saber se você tem alguma idéia sobre isso.

Foi útil?

Solução

@jatan

Obrigado por responder.Faz sentido.Você pode por favor me explicar MathContext no contexto de BigDecimal#método redonda.

Não há nada de especial sobre BigDecimal.round() vs. qualquer outro BigDecimal o método.Em todos os casos, a MathContext especifica o número de algarismos significativos e arredondamento técnica.Basicamente, há duas peças de cada MathContext.Há uma precisão, e há também um RoundingMode.

A precisão novamente especifica o número de dígitos significativos.Portanto, se você especificar 123 como um número, e pedir para 2 algarismos significativos, você está indo para obter 120.Ele pode ser mais claro se você pensar em termos de notação científica.

123 seria 1.23e2 em notação científica.Se você manter apenas 2 algarismos significativos, em seguida, você obter 1.2e2, ou 120.Reduzindo o número de algarismos significativos, podemos reduzir a precisão com que podemos especificar um número.

O RoundingMode parte especifica como devemos lidar com a perda de precisão.Para reutilizar o exemplo, se você usar 123 como o número e pedir para 2 algarismos significativos, já reduzido a sua precisão.Com um RoundingMode de HALF_UP (modo padrão), 123 vai se tornar 120.Com um RoundingMode de CEILING, você vai ter 130.

Por exemplo:

System.out.println(new BigDecimal("123.4",
                   new MathContext(4,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(2,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(2,RoundingMode.CEILING)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(1,RoundingMode.CEILING)));

Saídas:

123.4
1.2E+2
1.3E+2
2E+2

Você pode ver que tanto a precisão e o modo de arredondamento afetar a saída.

Outras dicas

Para o arredondamento apenas a parte fracionária de um BigDecimal, confira o BigDecimal.setScale(int newScale, int roundingMode) o método.

E. g.para alterar um número com três dígitos após o ponto decimal para um com dois dígitos, e o arredondamento para cima:

BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);

O resultado disso é um BigDecimal com o valor de 1,24 (por causa da regra de arredondamento para cima)

Eu gostaria de acrescentar aqui, alguns exemplos.Eu não encontrei-os em respostas anteriores, mas eu encontrá-los úteis para aqueles que talvez enganar algarismos significativos com o número de casas decimais.Vamos supor que temos tal contexto:

MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);

Para que este código:

BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);

é perfeitamente claro, que o resultado é 1.23E+3 como a galera disse acima.Primeiro algarismos significativos são 123...

Mas o que neste caso:

BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX);
System.out.println(d2);

seu número não será arredondado para 3 lugares após a vírgula - para alguém que não pode ser, intuitiva e vale a pena ressaltar.Em vez disso, ele será arredondado para o os primeiros 3 dígitos significativos, que neste caso são "4 5 4".Assim o código acima resulta em 4.55E-7 e não em 0.000 como alguém poderia esperar.

Exemplos semelhantes:

BigDecimal d3 = new BigDecimal(0.001000045477, MATH_CTX);
 System.out.println(d3);  // 0.00100

BigDecimal d4 = new BigDecimal(0.200000477, MATH_CTX);
 System.out.println(d4);   // 0.200

BigDecimal d5 = new BigDecimal(0.000000004, MATH_CTX);
    System.out.println(d5); //4.00E-9

Eu espero que isso óbvio, mas relevante exemplo seria útil...

Se eu estou entendendo bem, parece que está esperando o MathContext para controlar quantos dígitos deve ser mantido após o ponto decimal.Que não é o que ele serve.Especifica quantos dígitos para manter, total.Portanto, se você especificar que você deseja 3 algarismos significativos, isso é tudo que você vai conseguir.

Por exemplo, este:

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(20)));

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(10)));

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(5)));

saída:

1234567890.123456789
1234567890
1.2346E+9

Não é para se divertir.Na verdade, eu encontrei alguns on-line exemplo, que afirmaram que o uso de MathContext para arredondar os valores e números armazenados na BigDecimal.

Por exemplo,

Se MathContext está configurado para ter precision = 2 e rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294, é arredondado para 0.53

Então eu achei que é uma nova técnica e a usou para arredondamento finalidade.No entanto, ele se transformou em pesadelo, pois começou a arredondamento mesmo mentissa parte do número.

Por exemplo,

Number = 1.5294 é arredondado para 1.5

Number = 10.5294 é arredondado para 10

Number = 101.5294 é arredondado para 100

....e assim por diante

Portanto, este não é o comportamento esperado para o arredondamento (precisão = 2).

Ele parece estar tendo um pouco de lógica, pois, a partir fraseado eu posso dizer que ele leva dois primeiros dígitos (como a precisão é 2), do número e, em seguida, anexa 0 até o sem.de dígitos tornar-se mesmo como anterior não-arredondada quantidade ("checkout", a exemplo de 101.5294 ...)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top