Рассматривайте каждую дату по месяцам, а затем вычитайте, чтобы найти разницу.
var past_date = new Date('11/1/2014');
var current_date = new Date();
var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());
Это даст вам разницу между месяцами между двумя датами, игнорируя дни.
Используйте setRoundingMode
, явно задайте RoundingMode
, чтобы обрабатывать вашу проблему с полуточным раундом, а затем используйте шаблон формата для требуемого вывода.
Пример:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
дает выход:
12
123.1235
0.23
0.1
2341234.2125
Где dp = десятичное место, которое вы хотите, а значение является двойным.
double p = Math.pow(10d, dp);
double result = Math.round(value * p)/p;
Вы можете использовать следующий метод утилиты -
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
round(1.005,2);
или round(0.50594724957626620092, 20);
– Matthias Braun
29 March 2014 в 03:02
Поскольку я не нашел полного ответа по этой теме, я собрал класс, который должен правильно обрабатывать его, с поддержкой:
Использование довольно просто:
(Для этого примера я использую пользовательскую локаль)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Вот класс:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
На всякий случай кому-то все еще нужна помощь. Это решение отлично работает для меня.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
возвращает String
с желаемым выходом.
Предположим, что у вас есть
double d = 9232.129394d;
, вы можете использовать BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
или без BigDecimal
d = Math.round(d*100)/100.0d;
с обоими решениями d == 9232.13
RoundingMode.HALF_UP
неверно. Попробуйте с помощью 1.505
. Правильный способ - использовать BigDecimal.valueOf(d)
.
– Matthias Braun
29 March 2014 в 02:58
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
Ниже приведен фрагмент кода, показывающий, как отображать n цифр. Фокус в том, чтобы установить переменную pp в 1, за которой следуют n нулей. В приведенном ниже примере значение переменной pp имеет 5 нулей, поэтому будут отображаться 5 цифр.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
Вот краткое изложение того, что вы можете использовать, если хотите, чтобы результат был как String:
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
Вот пример того, какие библиотеки вы можете использовать, если хотите double
. Я бы не рекомендовал его для преобразования строк, хотя, поскольку double не может точно представлять то, что вы хотите (см., Например, здесь ):
Предполагая, что value
является double
, вы можете сделать:
(double)Math.round(value * 100000d) / 100000d
Это для 5-значной точности. Число нулей указывает количество десятичных знаков.
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.
– Robert Tupelo-Schneck
3 October 2012 в 19:51
Если вы используете технологию с минимальным JDK. Вот путь без каких-либо Java-библиотек:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
Если вы используете DecimalFormat
для преобразования double
в String
, это очень просто:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
Существует несколько значений перечисления RoundingMode
для выбора, в зависимости от поведение, которое вам требуется.
Вы можете использовать BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
Если вам действительно нужны десятичные числа для вычисления (и не только для вывода), не используйте бинарный формат с плавающей запятой, например double.
Use BigDecimal or any other decimal-based format.
Я использую BigDecimal для вычислений, но помните, что он зависит от размера чисел, с которыми вы имеете дело. В большинстве моих реализаций я нахожу, что синтаксический анализ из двойного или целого числа в Long достаточно для вычисления очень большого числа.
На самом деле, я недавно использовал parsed-to-Long для получения точных представлений (как против шестнадцатеричных результатов) в графическом интерфейсе для чисел, больших как ################################# символов (как пример). [/ д2]
Вы можете использовать класс DecimalFormat.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
Double.valueOf()
была выбрана над Double.parseDouble()
? Метод valueOf()
возвращает объект Double
, а parseDouble()
возвращает примитив double
. С учетом того, как написан текущий код, вы также применяете автоматическое распаковывание к возврату, чтобы передать его в примитив, который ожидает ваша переменная twoDouble
, дополнительную операцию байт-кода. Я бы изменил ответ, чтобы использовать parseDouble()
.
– ecbrodie
3 December 2015 в 07:25
Для этого мы можем использовать этот форматтер:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
или:
DecimalFormat df = new DecimalFormat("0.00"); :
Используйте этот метод для получения двух десятичных знаков:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Определение этих значений:
91.32
5.22
11.5
1.2
2.6
Используя этот метод, мы можем получить следующие результаты:
91.32
5.22
11.50
1.20
2.60
Попробуйте это: org.apache.commons.math3.util.Precision.round (double x, int scale)
Домашняя страница библиотеки математики Apache Commons: http://commons.apache.org/ proper / commons-math / index.html
Внутренняя реализация этого метода:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
Кратким решением:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) Math.round(value * scale) / scale;
}
См. также https://stackoverflow.com/a/22186845/212950 Благодаря jpdymond за это.
Я согласен с выбранным ответом на использование DecimalFormat
--- или альтернативно BigDecimal
.
Пожалуйста, сначала прочтите Обновление ниже!
Однако, если вы хотите округлить двойное значение и получить результат значения double
, вы можете использовать org.apache.commons.math3.util.Precision.round(..)
, как указано выше. Реализация использует BigDecimal
, медленная и создает мусор. Подобный, но быстрый и не содержащий мусора метод предоставляется утилитой DoubleRounder
в библиотеке decimal4j:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Будет выводиться
0.667
0.666
1000.0
9.00800700601E10
См. 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.
Вы также можете использовать
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
, чтобы убедиться, что у вас есть конечные 0.
Decimal mode
использует RoundingMode.HALF_EVEN.
– EndermanAPM
27 September 2016 в 15:40
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
доставит вам BigDecimal
. Чтобы получить строку из нее, просто вызовите этот метод BigDecimal
toString
или метод toPlainString
для Java 5+ для строки простого формата.
Пример программы:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
new BigDecimal(doubleVar)
, так как вы можете столкнуться с проблемами с округлением плавающих точек
– Edd
26 January 2015 в 18:57
double val = 265.335;
, BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
= & gt; 265.34
, но (new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
= & gt; 265.33
.
– ToolmakerSteve
28 August 2015 в 03:41
Java Java Real-How [to] отправляет это решение, которое также совместимо для версий до Java 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
@Milhous: десятичный формат округления превосходный:
Вы также можете использовать
DecimalFormat df = new DecimalFormat("#.00000"); df.format(0.912385);
, чтобы убедиться, что у вас есть конечные 0.
blockquote>Я бы добавил, что этот метод очень хорош в обеспечении реального числового механизма округления - не только визуально, но и при обработке.
Гипотетическая: вам нужно реализовать округление в программу GUI. Чтобы изменить точность / точность результата, просто измените формат каретки (т. Е. В скобках). Так что:
DecimalFormat df = new DecimalFormat("#0.######"); df.format(0.912385);
вернется как результат:
0.912385
DecimalFormat df = new DecimalFormat("#0.#####"); df.format(0.912385);
вернется как результат:
0.91239
DecimalFormat df = new DecimalFormat("#0.####"); df.format(0.912385);
будет return в качестве выхода:
0.9124
[EDIT: также, если формат каретки похож на («# 0. ############»), и вы вводите десятичную, например 3.1415926, для аргументации, DecimalFormat не производит никакого мусора (например, конечных нулей) и вернет:
3.1415926
.. если вы так наклонены. Конечно, это немного многословно для симпатии некоторых разработчиков, но эй, у него низкий объем памяти во время обработки и очень легко реализуется.]Таким образом, красота DecimalFormat заключается в том, что она одновременно обрабатывает внешний вид строки, а также уровень точности округления. Эрго: вы получаете два преимущества по цене одной реализации кода. ;)
double
. Используйте BigDecimal или любой другой десятичный формат.
– Paŭlo Ebermann
3 July 2011 в 20:57
Имейте в виду, что String.format () и DecimalFormat производят строку, используя стандартный язык Locale. Таким образом, они могут писать форматированное число с точкой или запятой в качестве разделителя между целыми и десятичными частями. Чтобы убедиться, что округленная строка находится в формате, который вы хотите использовать java.text.NumberFormat, так:
Locale locale = Locale.ENGLISH;
NumberFormat nf = NumberFormat.getNumberInstance(locale);
// for trailing zeros:
nf.setMinimumFractionDigits(2);
// round to 2 digits:
nf.setMaximumFractionDigits(2);
System.out.println(nf.format(.99));
System.out.println(nf.format(123.567));
System.out.println(nf.format(123.0));
Будет печатать на английском языке (независимо от того, что у вас есть): 0.99 123.57 123.00
Пример из Farenda - , как правильно преобразовать double в String .
Если вы рассматриваете 5 или n число десятичных чисел. Может быть, этот ответ решает вашу проблему.
double a = 123.00449;
double roundOff1 = Math.round(a*10000)/10000.00;
double roundOff2 = Math.round(roundOff1*1000)/1000.00;
double roundOff = Math.round(roundOff2*100)/100.00;
System.out.println("result:"+roundOff);
Выход будет: 123.01 это можно решить с помощью петлевой и рекурсивной функции.
Как правило, округление выполняется путем масштабирования: round(num / p) * p
/**
* MidpointRounding away from zero ('arithmetic' rounding)
* Uses a half-epsilon for correction. (This offsets IEEE-754
* half-to-even rounding that was applied at the edge cases).
*/
double RoundCorrect(double num, int precision) {
double c = 0.5 * EPSILON * num;
// double p = Math.pow(10, precision); //slow
double p = 1; while (precision--> 0) p *= 10;
if (num < 0)
p *= -1;
return Math.round((num + c) * p) / p;
}
// testing edge cases
RoundCorrect(1.005, 2); // 1.01 correct
RoundCorrect(2.175, 2); // 2.18 correct
RoundCorrect(5.015, 2); // 5.02 correct
RoundCorrect(-1.005, 2); // -1.01 correct
RoundCorrect(-2.175, 2); // -2.18 correct
RoundCorrect(-5.015, 2); // -5.02 correct
DecimalFormat - лучший способ вывода, но я не предпочитаю его. Я всегда делаю это все время, потому что он возвращает двойное значение. Поэтому я могу использовать его больше, чем просто вывод.
Math.round(selfEvaluate*100000d.0)/100000d.0;
ИЛИ
Math.round(selfEvaluate*100000d.0)*0.00000d1;
Если вам нужно большое значение десятичных знаков, вы можете использовать BigDecimal. В любом случае .0
важно. Без него округление 0,333333d5 возвращает 0,33333 и допускается только 9 цифр. Вторая функция без .0
имеет проблемы с возвратом 0.30000 0.30000000000000004.
Я пришел сюда, просто желая простого ответа о том, как округлить число. Это дополнительный ответ, чтобы обеспечить это.
Наиболее распространенным случаем является использование Math.round()
.
Math.round(3.7) // 4
Числа округлены до ближайшего целого числа. Значение .5
округляется. Если вам нужно другое поведение округления, вы можете использовать одну из других функций Math . См. Сравнение ниже.
Как указано выше, это округляет до ближайшего целого числа. .5
округлые десятичные числа. Этот метод возвращает int
.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
Любое десятичное значение округляется до следующего целого числа. Он подходит к потолку. Этот метод возвращает значение double
.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
Любое десятичное значение округляется до следующего целого. Этот метод возвращает значение double
.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
Это похоже на раунд в том, что десятичные значения округляются до ближайшего целого. Однако, в отличие от round
, .5
значения округляются до четного целого. Этот метод возвращает значение double
.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
Как отмечали некоторые другие, правильным ответом является использование либо DecimalFormat
, либо BigDecimal
. Плавающая точка не имеет десятичных мест , поэтому вы не можете округлить / усечь до определенного числа из них в первую очередь. Вы должны работать в десятичном радиксе, и это то, что делают эти два класса.
Я отправляю следующий код в качестве встречного примера для всех ответов в этом потоке и, действительно, по всему StackOverflow (и в другом месте), которые рекомендуют умножение с последующим усечением, за которым следует разделение. Для сторонников этой методики необходимо объяснить, почему следующий код производит неправильный вывод в более чем 92% случаев.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Вывод этой программы:
10001 trials 9251 errors
EDIT: Чтобы ответить на некоторые комментарии ниже, я отредактирую часть модуля тестового цикла с помощью BigDecimal
и new MathContext(16)
для работы модуля следующим образом:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Результат:
10001 trials 4401 errors
100 trials 94 errors
Вы должны начать с теста, который проходит, и показать, что введение округления прерывает тест.
– Peter Lawrey
2 March 2014 в 13:26
double
без ошибок ideone.com/BVCHh3
– Peter Lawrey
2 March 2014 в 13:42
"#.##"
, округленияHALF_UP
.256.335f
- & gt;"256.33"
... (пример проистекает из комментариев к ответу @ asterite). – bigstones 11 December 2015 в 12:43