Как я могу усечь двойную дробь только до двух десятичных знаков в Java?

98

Например, у меня есть переменная 3.545555555, которую я хотел бы усечь до 3,54.

Джонни
источник
21
Это НЕ дубликат. Усечение и округление - две совершенно разные вещи.
markthegrea 01
Согласен, не знаю, почему это помечено как повторяющееся.
Bassinator

Ответы:

147

Если вы хотите, чтобы это отображалось, используйте java.text.DecimalFormat:

 new DecimalFormat("#.##").format(dblVar);

Если вам это нужно для расчетов, используйте java.lang.Math:

 Math.floor(value * 100) / 100;
Божо
источник
50
При этом не будет отображаться усеченное значение 3,545555555 до 3,54, а будет округлено до 3,55. DecimalFormat.setRoundingMode () должен иметь значение RoundingMode.FLOOR;
Christian García
9
это не работает для меня Math.floor (9,62 * 100) / 100 дает 9,61
Мани
4
Использование floorдля усечения работает только для положительных значений.
Dev
4
@ ChristianGarcía Усечение правильно сделано с , RoundingMode.DOWNкак RoudingMode.FLOORвсегда округляется в сторону отрицательной бесконечности.
Dev
46
DecimalFormat df = new DecimalFormat(fmt);
df.setRoundingMode(RoundingMode.DOWN);
s = df.format(d);

Проверить наличие RoundingModeи DecimalFormat.

Седрик Дюбур
источник
Не отвечает на вопрос, в котором запрашивается усечение, а не округление.
Basil Bourque
8
@BasilBourque RoundingMode.DOWN - это усечение. Сравните с другими ответами, которые неправильно рекомендуют функции пола (пол усекает только положительные числа), это работает правильно как для положительных, так и для отрицательных значений.
Dev
1
@Dev Я поправляюсь. Теперь я вижу, что DOWNэто действительно имеет эффект усечения как для положительных, так и для отрицательных чисел. Как видно из таблицы примеров в док .
Basil Bourque
25

Bit Old Forum, ни один из приведенных выше ответов не работал как для положительных, так и для отрицательных значений (я имею в виду расчет и просто усечение без округления). Из ссылки Как округлить число до n десятичных знаков в Java

private static BigDecimal truncateDecimal(double x,int numberofDecimals)
{
    if ( x > 0) {
        return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_FLOOR);
    } else {
        return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_CEILING);
    }
}

У меня этот метод сработал.

System.out.println(truncateDecimal(0, 2));
    System.out.println(truncateDecimal(9.62, 2));
    System.out.println(truncateDecimal(9.621, 2));
    System.out.println(truncateDecimal(9.629, 2));
    System.out.println(truncateDecimal(9.625, 2));
    System.out.println(truncateDecimal(9.999, 2));
    System.out.println(truncateDecimal(-9.999, 2));
    System.out.println(truncateDecimal(-9.0, 2));

Полученные результаты :

0.00
9.62
9.62
9.62
9.62
9.99
-9.99
-9.00
Мани
источник
Это ответ, который можно масштабировать для большего количества тестовых примеров
диего матос - кеке
вернуть новый BigDecimal (x) .setScale (numberofDecimals, RoundingMode.DOWN) .doubleValue ();
Шимон Дудкин,
кажется, округление вниз похоже на то, что вы имели в виду: docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html
Шимон Дудкин
9

Прежде всего обратите внимание, что a double- это двоичная дробь и на самом деле не имеет десятичных знаков.

Если вам нужны десятичные разряды, используйте a BigDecimal, у которого есть setScale()метод усечения, или используйте, DecimalFormatчтобы получить String.

Майкл Боргвардт
источник
7

Если по какой-либо причине вы не хотите использовать, BigDecimalвы можете doubleпреобразовать его вint чтобы усечь его.

Если вы хотите усечь до единственного места:

  • просто передать в int

На десятое место:

  • умножить на десять
  • бросить в int
  • отбросить обратно к double
  • и разделите на десять.

сотых место

  • умножить и разделить на 100 и т. д.

Пример:

static double truncateTo( double unroundedNumber, int decimalPlaces ){
    int truncatedNumberInt = (int)( unroundedNumber * Math.pow( 10, decimalPlaces ) );
    double truncatedNumber = (double)( truncatedNumberInt / Math.pow( 10, decimalPlaces ) );
    return truncatedNumber;
}

В этом примере decimalPlacesэто будет количество мест, ПРОШЕДШИЕ те места, в которые вы хотите перейти, поэтому 1 будет округлено до десятых , 2 до сотых и так далее (0 округляет до единиц , а отрицательное - до десятков. , так далее.)

Тарвис
источник
3
Это ужасное общее решение. И умножение, и приведение приведут к тому, что данные будут отброшены, что приведет к тому, что фактически будут случайными числами, если они unroundedNumberбудут достаточно большими. Это может сработать для примера в вопросе, но общее решение должно работать для любого double.
blm
6

Форматирование в виде строки и преобразование обратно в double, я думаю, даст вам желаемый результат.

Двойное значение не будет круглым (), floor () или ceil ().

Быстрое исправление этого может быть:

 String sValue = (String) String.format("%.2f", oldValue);
 Double newValue = Double.parseDouble(sValue);

Вы можете использовать sValue для отображения или newValue для расчета.

Джао Асси
источник
1
Для меня это округление до ближайшего значения. Например: 0,018 конвертируется в 0,02, когда я это сделал.
Каран Патель
3

Может быть Math.floor(value * 100) / 100? Помните, что такие значения 3.54могут быть не совсем точно представлены с помощью double.

Влад
источник
3

Вы можете использовать объект NumberFormat Class для выполнения задачи.

// Creating number format object to set 2 places after decimal point
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);            
nf.setGroupingUsed(false);

System.out.println(nf.format(precision));// Assuming precision is a double type variable
Рушди Шамс
источник
3

3.545555555, чтобы получить 3.54. Попробуйте следующее:

    DecimalFormat df = new DecimalFormat("#.##");

    df.setRoundingMode(RoundingMode.FLOOR);

    double result = new Double(df.format(3.545555555);

Это даст = 3,54!

Анкуш Г
источник
Но я получу 3,5, если установлю значение 3,50123
Сайрус
1

Вот метод, который я использую:

double a=3.545555555; // just assigning your decimal to a variable
a=a*100;              // this sets a to 354.555555
a=Math.floor(a);      // this sets a to 354
a=a/100;              // this sets a to 3.54 and thus removing all your 5's

Это также можно сделать:

a=Math.floor(a*100) / 100;
Митчелл Хайнс
источник
0

Возможно следующее:

double roundTwoDecimals(double d) { 
      DecimalFormat twoDForm = new DecimalFormat("#.##"); 
      return Double.valueOf(twoDForm.format(d));
}  
Ритеш Мэнджи
источник
Смотрите другие ответы. Вы не можете сделать это надежно, если ответ должен быть представлен в виде с плавающей запятой.
Маркиз Лорн,
0

Быстрая проверка - использовать метод Math.floor. Я создал метод проверки двойника на два или меньше десятичных знаков ниже:

public boolean checkTwoDecimalPlaces(double valueToCheck) {

    // Get two decimal value of input valueToCheck 
    double twoDecimalValue = Math.floor(valueToCheck * 100) / 100;

    // Return true if the twoDecimalValue is the same as valueToCheck else return false
    return twoDecimalValue == valueToCheck;
}
chris31389
источник
-1

У меня немного модифицированная версия Mani .

private static BigDecimal truncateDecimal(final double x, final int numberofDecimals) {
    return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_DOWN);
}

public static void main(String[] args) {
    System.out.println(truncateDecimal(0, 2));
    System.out.println(truncateDecimal(9.62, 2));
    System.out.println(truncateDecimal(9.621, 2));
    System.out.println(truncateDecimal(9.629, 2));
    System.out.println(truncateDecimal(9.625, 2));
    System.out.println(truncateDecimal(9.999, 2));
    System.out.println(truncateDecimal(3.545555555, 2));

    System.out.println(truncateDecimal(9.0, 2));
    System.out.println(truncateDecimal(-9.62, 2));
    System.out.println(truncateDecimal(-9.621, 2));
    System.out.println(truncateDecimal(-9.629, 2));
    System.out.println(truncateDecimal(-9.625, 2));
    System.out.println(truncateDecimal(-9.999, 2));
    System.out.println(truncateDecimal(-9.0, 2));
    System.out.println(truncateDecimal(-3.545555555, 2));

}

Выход:

0.00
9.62
9.62
9.62
9.62
9.99
9.00
3.54
-9.62
-9.62
-9.62
-9.62
-9.99
-9.00
-3.54
HolyLance
источник
-2

Это сработало для меня:

double input = 104.8695412  //For example

long roundedInt = Math.round(input * 100);
double result = (double) roundedInt/100;

//result == 104.87

Мне лично нравится эта версия, потому что она фактически выполняет численное округление, а не путем преобразования ее в строку (или аналогичную), а затем ее форматирования.

Радуга975
источник
1
Исходный вопрос касается усечения, а не округления. Кроме того, преобразование двойного значения в длинное вообще не будет работать, если оно достаточно велико.
blm
-2
//if double_v is 3.545555555
String string_v= String.valueOf(double_v);
int pointer_pos = average.indexOf('.');//we find the position of '.'
string_v.substring(0, pointer_pos+2));// in this way we get the double with only 2 decimal in string form
double_v = Double.valueOf(string_v);//well this is the final result

ну, это может быть немного неудобно, но я думаю, что это может решить вашу проблему :)

user5251903
источник
Этот код выполняет свою работу, но он не элегантен и имеет низкую производительность. Это может быть нормально в школьных проектах, но определенно не решение, которое кто-то будет использовать в производственной среде для любой системы, если вы не хотите, чтобы впоследствии у вас возникли головные боли.
cbaldan 06