То, что я хотел бы, - это метод преобразования двойного числа в строку, которая округляется с использованием метода половинного увеличения - то есть, если десятичное число округляется до 5, оно всегда округляется до следующего числа. Это стандартный метод округления, которого большинство людей ожидают в большинстве ситуаций.
Я также хотел бы, чтобы отображались только значащие цифры - то есть не должно быть никаких завершающих нулей.
Я знаю один способ сделать это, чтобы использовать String.format
метод:
String.format("%.5g%n", 0.912385);
возвращает:
0.91239
это здорово, однако всегда отображает числа с 5 десятичными разрядами, даже если они не имеют значения:
String.format("%.5g%n", 0.912300);
возвращает:
0.91230
Другой метод заключается в использовании DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
возвращает:
0.91238
Однако, как вы можете видеть, для этого используется округление до половины. То есть будет округляться, если предыдущая цифра четная. Что я хотел бы это:
0.912385 -> 0.91239
0.912300 -> 0.9123
Каков наилучший способ добиться этого в Java?
"#.##"
округленияHALF_UP
.256.335f
->"256.33"
... (пример взят из комментариев к ответу @ asterite).Предполагая , что
value
этоdouble
, вы можете сделать:Это для точности 5 цифр. Количество нулей указывает количество десятичных знаков.
источник
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.265.335
действительно означает265.335 += tolerance
, что допуск зависит от предыдущих операций и диапазона входных значений. Мы не знаем истинного, точного значения. При краевых значениях любой ответ, возможно, является правильным. Если нам нужно быть точным, мы не должны работать в два раза.fail
Здесь не в преобразовании обратно в два раза. Это в OP, думая, что он может полагаться на входящее,265.335
как являющееся именно этим.получит тебя
BigDecimal
. Для того, чтобы получить строку из него, просто назвать этоBigDecimal
«ыtoString
метод, илиtoPlainString
метод Java 5+ для простой строки формата.Пример программы:
источник
new BigDecimal(doubleVar)
как вы можете столкнуться с проблемами с округлением чисел с плавающей запятойdouble val = 265.335;
,BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.34
, но(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.33
.Вы также можете использовать
чтобы убедиться, что у вас есть конечные 0.
источник
RoundingMode.
Decimal mode
используетRoundingMode.HALF_EVEN.
Как отметили некоторые другие, правильный ответ должен использовать либо
DecimalFormat
илиBigDecimal
. Плавающая точка не имеет десятичных разрядов, поэтому вы не можете округлять / усекать их до определенного числа. Вы должны работать с десятичным основанием, и это то, что делают эти два класса.Я публикую следующий код в качестве контрпримера ко всем ответам в этой теме и даже по всему StackOverflow (и в других местах), которые рекомендуют умножение с последующим усечением и последующим делением. Сторонники этого метода обязаны объяснить, почему следующий код дает неправильный вывод в более чем 92% случаев.
Выход этой программы:
РЕДАКТИРОВАТЬ: Чтобы обратиться к некоторым комментариям ниже, я переделал часть модуля тестового цикла, используя
BigDecimal
иnew MathContext(16)
для операции модуля следующим образом:Результат:
источник
100 trials 94 errors
Вы должны начать с теста, который проходит успешно , и показать, что введение округления нарушает тест.double
без ошибок ideone.com/BVCHh3Предположим, у вас есть
ты можешь использовать
BigDecimal
или без BigDecimal
с обоими решениями
d == 9232.13
источник
RoundingMode.HALF_UP
неправильным. Попробуйте это с1.505
. Правильный способ заключается в использованииBigDecimal.valueOf(d)
.Вы можете использовать класс DecimalFormat.
источник
Double.valueOf()
был выбранDouble.parseDouble()
?valueOf()
Метод возвращаетDouble
объект, в то время какparseDouble()
будет возвращатьdouble
примитивно. При способе написания текущего кода вы также применяете автоматическую распаковку к возврату, чтобы привести его к примитиву, ожидаемому вашейtwoDouble
переменной, дополнительной операции с байт-кодом. Я бы изменил ответ, чтобы использоватьparseDouble()
вместо этого.Double.parseDouble()
нуженString
вклад.Как к Java Real в постах это решение, которое также совместим для версий до Java 1.6.
источник
источник
Math.floor(x + 0.5)
иMath.round(x)
@Milhous: превосходный десятичный формат для округления:
Я хотел бы добавить, что этот метод очень хорош в обеспечении фактического числового механизма округления - не только визуально, но и при обработке.
Гипотетический: вы должны внедрить механизм округления в программу с графическим интерфейсом. Чтобы изменить точность / точность вывода результатов, просто измените формат каретки (то есть в скобках). Так что:
вернется в качестве вывода:
0.912385
вернется в качестве вывода:
0.91239
вернется в качестве вывода:
0.9124
[РЕДАКТИРОВАТЬ: также, если формат каретки такой («# 0. ############»), и вы вводите десятичное число, например, 3.1415926, для аргумента, DecimalFormat не производит никакого мусора ( например, конечные нули) и вернет:
3.1415926
.. если вы склонны к этому. Конечно, это немного многословно для симпатий некоторых разработчиков - но, эй, у него мало места в памяти во время обработки и его очень легко реализовать.]Таким образом, красота DecimalFormat заключается в том, что он одновременно обрабатывает внешний вид строки, а также уровень точности округления. Ergo: вы получаете два преимущества по цене одной реализации кода. ;)
источник
double
. Используйте BigDecimal или любой другой десятичный формат.Вот краткое изложение того, что вы можете использовать, если хотите получить результат в виде строки:
DecimalFormat # setRoundingMode () :
BigDecimal # setScale ()
Вот предложение о том, какие библиотеки вы можете использовать, если хотите,
double
в результате. Я бы не рекомендовал это для преобразования строк, так как double может быть не в состоянии точно представить, что вы хотите (см., Например, здесь ):Точность от Apache Commons Math
Функции от Colt
Утилиты из Века
источник
Вы можете использовать следующий метод утилиты:
источник
round(1.005,2);
илиround(0.50594724957626620092, 20);
Краткое решение:
См. Также https://stackoverflow.com/a/22186845/212950. Спасибо jpdymond за это.
источник
Вы можете использовать BigDecimal
См .: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
источник
Попробуйте это: org.apache.commons.math3.util.Precision.round (double x, int scale)
См. Http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html.
Домашняя страница библиотеки математики Apache Commons: http://commons.apache.org/proper/commons-math/index.html
Внутренняя реализация этого метода:
источник
Поскольку я не нашел полного ответа на эту тему, я собрал класс, который должен обрабатывать это правильно, с поддержкой:
Использование довольно просто :
(Ради этого примера я использую пользовательскую локаль)
Вот класс :
источник
Если вам действительно нужны десятичные числа для расчета (и не только для вывода), не используйте двоичный формат с плавающей запятой, такой как double.
Я использую BigDecimal для расчетов, но имейте в виду, что это зависит от размера чисел, с которыми вы имеете дело. В большинстве моих реализаций я считаю, что синтаксический анализ от двойного или целого до длинного вполне достаточен для очень большого числа вычислений.
На самом деле, я недавно использовал parsed-to-Long, чтобы получить точные представления (в отличие от шестнадцатеричных результатов) в графическом интерфейсе для чисел, таких как ################## ############### символы (как пример).
источник
Для достижения этого мы можем использовать этот форматер:
или:
Используйте этот метод, чтобы получить всегда два десятичных знака:
Определение этого значения:
Используя метод, мы можем получить следующие результаты:
Демо онлайн.
источник
На всякий случай, если кому-то все еще нужна помощь с этим. Это решение отлично работает для меня.
возвращает
String
с желаемым выходом.источник
Я согласен с выбранным ответом использовать
DecimalFormat
--- или в качестве альтернативыBigDecimal
.Пожалуйста, сначала прочтите Обновление ниже!
Однако , если вы действительно хотите , чтобы закруглить двойное значение и получитьdouble
результат значения, вы можете использовать ,org.apache.commons.math3.util.Precision.round(..)
как упоминалось выше. Реализация используетBigDecimal
, медленно и создает мусор.Аналогичный, но быстрый и не содержащий мусора метод предоставляетсяDoubleRounder
утилитой из библиотеки decimal4j:Будет выходной
См. Https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility.
Отказ от ответственности: я участвую в проекте decimal4j.
Обновление: как отметил @iaforek, DoubleRounder иногда возвращает нелогичные результаты. Причина в том, что он выполняет математически правильное округление. Например
DoubleRounder.round(256.025d, 2)
будет округлено до 256,02, поскольку двойное значение, представленное как 256,025d, несколько меньше рационального значения 256,025 и, следовательно, будет округлено в меньшую сторону.Ноты:
BigDecimal(double)
конструктора (но не вvalueOf(double)
котором используется строковый конструктор).По этим причинам и всему, что упомянуто выше в этом посте, я не могу рекомендовать использовать DoubleRounder .
источник
Фрагмент кода ниже показывает, как отображать n цифр. Хитрость заключается в том, чтобы установить переменную pp в 1, за которой следуют n нулей. В приведенном ниже примере значение переменной pp имеет 5 нулей, поэтому будут отображаться 5 цифр.
источник
Если вы используете
DecimalFormat
для преобразованияdouble
вString
, это очень просто:Есть несколько
RoundingMode
значений enum на выбор, в зависимости от требуемого поведения.источник
Я пришел сюда просто, чтобы получить простой ответ о том, как округлить число. Это дополнительный ответ, чтобы обеспечить это.
Как округлить число в Java
Наиболее распространенным случаем является использование
Math.round()
.Числа округляются до ближайшего целого числа.
.5
Значение округляется. Если вам нужно другое поведение округления, чем это, вы можете использовать одну из других математических функций. Смотрите сравнение ниже.круглый
Как указано выше, это округляет до ближайшего целого числа.
.5
десятичные числа округлять вверх. Этот метод возвращаетint
.перекрывать
Любое десятичное значение округляется до следующего целого числа. Идет к потолку . Этот метод возвращает
double
.этаж
Любое десятичное значение округляется до следующего целого числа. Этот метод возвращает
double
.ечать
Это похоже на округление в том, что десятичные значения округляют до ближайшего целого числа. Однако, в отличие от
round
,.5
значения округляются до четного целого числа. Этот метод возвращаетdouble
.источник
Если вы используете технологию, которая имеет минимальный JDK. Вот способ без каких-либо библиотек Java:
источник
DecimalFormat - лучший способ вывода, но я не предпочитаю его. Я всегда делаю это все время, потому что он возвращает двойное значение. Так что я могу использовать это больше, чем просто вывод.
ИЛИ
Если вам нужно большое значение десятичных разрядов, вы можете использовать вместо него BigDecimal. В любом случае
.0
это важно. Без этого допускается округление 0.33333d5 до 0.33333 и допускается только 9 цифр. Вторая функция без.0
проблем с 0.30000 возвращает 0.30000000000000004.источник
вот мой ответ:
источник
Поэтому, прочитав большинство ответов, я понял, что большинство из них не будут точными, на самом деле использование
BigDecimal
кажется лучшим выбором, но если вы не понимаете, как этоRoundingMode
работает, вы неизбежно потеряете точность. Я понял это при работе с большими числами в проекте и подумал, что это может помочь другим людям, испытывающим трудности с округлением чисел. Например.Вы ожидаете получить
1363.28
в качестве вывода, но в итоге вы получите1363.27
, чего не ожидаете, если не знаете, чтоRoundingMode
делает. Итак, изучая документы Oracle , вы найдете следующее описание дляRoundingMode.HALF_UP
.Итак, зная это, мы поняли, что не получим точное округление, если не хотим округлить до ближайшего соседа . Таким образом, чтобы выполнить адекватный раунд, нам нужно было бы выполнить цикл от
n-1
десятичной дроби до желаемых десятичных знаков. Например.Это в конечном итоге даст нам ожидаемый результат, который будет
1363.28
.источник
Где dp = десятичное место, которое вы хотите, а значение является двойным.
источник
1.0
дляvalue = 1.005
аdp = 2
. Используйте это вместо этого.Имейте в виду, что String.format () и DecimalFormat создают строку, используя локаль по умолчанию. Таким образом, они могут написать отформатированное число с точкой или запятой в качестве разделителя между целыми и десятичными частями. Чтобы убедиться, что округленная строка соответствует желаемому формату, используйте java.text.NumberFormat следующим образом:
Будет напечатан на английском языке (независимо от того, какой у вас язык): 0,99 123,57 123,00
Пример взят из Farenda - как правильно конвертировать double в String .
источник
В общем, округление выполняется путем масштабирования:
round(num / p) * p
источник