Использование java.math.MathContext

Недавно я попытался понять использование java.math.MathContext, но не смог правильно понять. Используется ли для округления java.math.BigDecimal. Если да, то почему бы не округлить десятичные цифры, но даже часть мантиссы.

Из документации по API я узнал, что она соответствует стандарту, указанному в спецификациях ANSI X3.274-1996и ANSI X3.274-1996/AM 1-2000спецификациях, но я не получил их для чтения в Интернете.

Пожалуйста, дайте мне знать, если у вас есть идеи по этому поводу.

11.08.2008 05:23:02
5 ОТВЕТОВ
РЕШЕНИЕ

@jatan

Спасибо за ответ. Это имеет смысл. Не могли бы вы объяснить мне MathContext в контексте метода BigDecimal # round.

В этом нет ничего особенного BigDecimal.round() против любого другого BigDecimalметода. Во всех случаях MathContextуказывается количество значащих цифр и метод округления. В основном, есть две части каждого MathContext. Там есть точность, а также есть RoundingMode.

Точность снова указывает количество значащих цифр. Так что, если вы укажете 123число и попросите 2 значащие цифры, вы получите 120. Это может быть яснее, если вы думаете с точки зрения научной нотации.

123будет 1.23e2в научной нотации. Если вы оставите только 2 значащие цифры, то вы получите 1.2e2, или 120. Сокращая количество значащих цифр, мы уменьшаем точность, с которой мы можем указать число.

RoundingModeЧасть определяет , как мы должны справиться с потерей точности. Чтобы повторно использовать пример, если вы используете 123в качестве числа и запрашиваете 2 значащие цифры, вы снизили свою точность. С RoundingModeо HALF_UP(режим по умолчанию), 123станет 120. С RoundingModeо CEILING, вы получите 130.

Например:

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)));

Выходы:

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

Вы можете видеть, что как точность, так и режим округления влияют на вывод.

48
11.08.2008 06:06:48
Есть ли способ форматирования 123.4с использованием 2 значащих цифр, в результате получается строка вроде 120? Это 2 значащие цифры (как есть 1.2E2), потому что конечные нули традиционно не включаются в поиск значащих цифр, если нет конечной десятичной дроби. И для моих целей, если число, которое нужно отформатировать, было 103.4, мне все равно, что вы не можете сказать, что в полученном 100числе есть 2 сиг фига . Я просто хочу более простой / чистый просмотр номеров.
hepcat72 7.02.2017 15:00:40

Если я вас правильно понимаю, похоже, вы ожидаете, что MathContext будет контролировать, сколько цифр следует хранить после десятичной точки. Это не то, для чего это. Указывает, сколько цифр сохранить, всего . Поэтому, если вы укажете, что хотите 3 значащих цифры, это все, что вы получите.

Например, это:

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)));

будет выводить:

1234567890.123456789
1234567890
1.2346E+9
4
11.08.2008 05:44:00
Спасибо. Как бы я выбрал количество цифр после десятичного числа?
Drew 7.03.2012 22:13:17
Это не совсем вопрос для BigDecimal. С BigDecimal вы должны вместо этого указывать количество значащих цифр. Сколько цифр после десятичной точки должно быть определено при форматировании для отображения. Вы можете контролировать это с помощью String.format () или DecimalFormat.format ().
Derek Park 9.03.2012 18:48:51
@ Я думаю, вы можете использовать для этого метод BigDecimal.setScale . Первый параметр (масштаб) указывает, сколько чисел вы хотите сохранить после десятичной точки, а второй параметр (roundingMode) определяет желаемое поведение округления.
Quazi Irfan 21.01.2018 06:59:32
@Drew Вот ответ, который объясняет это более подробно.
Quazi Irfan 21.01.2018 12:39:17

Это не для удовольствия. На самом деле я нашел несколько онлайн-примеров, в которых указано, как MathContextокруглять суммы / числа, хранящиеся в BigDecimal.

Например,

Если MathContextнастроен на наличие precision = 2иrounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294, Имеет закругленные до 0,53

Поэтому я подумал, что это более новая техника, и использовал ее для округления. Однако это превратилось в кошмар, потому что оно начало округлять даже ментисную часть числа.

Например,

Number = 1.5294 округляется до 1.5

Number = 10.5294 округляется до 10

Number = 101.5294 округляется до 100

.... и так далее

Так что это не то поведение, которое я ожидал для округления (так как точность = 2).

Кажется, у него есть некоторая логика, потому что из patter я могу сказать, что он берет первые две цифры (с точностью до 2) числа, а затем добавляет 0 до нуля. цифры становятся такими же, как и необоснованная сумма (см. пример 101.5294 ...)

4
23.12.2015 10:09:10
так что вы можете предложить вместо решения, а?
Sumit Ramteke 19.02.2014 06:55:28

Для округления только дробной части BigDecimal, проверьте BigDecimal.setScale(int newScale, int roundingMode)метод.

Например, чтобы изменить число с тремя цифрами после десятичной точки на одно с двумя цифрами и округлить в большую сторону:

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

Результатом этого является BigDecimal со значением 1.24 (из-за правила округления)

67
16.11.2010 12:55:27
Это ответ, который хотят получить люди, работая с фиксированными десятичными числами и сохраняя фиксированное количество десятичных знаков. Не знаю, почему Sun испортила здесь «точность» стиля с плавающей точкой, но это то, что MathContext.
Thomas W 28.04.2013 01:39:43

Я бы добавил сюда несколько примеров. Я не нашел их в предыдущих ответах, но нахожу их полезными для тех, кто может вводить в заблуждение значащие цифры с количеством знаков после запятой . Предположим, у нас есть такой контекст:

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

Для этого кода:

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

совершенно ясно, что ваш результат такой, 1.23E+3как сказали парни выше. Первые значимые цифры 123 ...

Но что в этом случае:

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

Ваш номер не будет округлен до 3 мест после запятой - для кого-то это может быть не интуитивно понятно и стоит подчеркнуть. Вместо этого он будет округлен до первых 3 значащих цифр , которые в данном случае равны «4 5 4». Таким образом, приведенный выше код приводит к тому, 4.55E-7а не 0.000к тому, чего кто-то мог ожидать

Подобные примеры:

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

Я надеюсь, что этот очевидный, но соответствующий пример будет полезен ...

13
11.04.2014 08:05:46