Обрезать более двух завершающих нулей в BigDecimal

Что было бы хорошим способом обрезать более двух конечных нулей для BigDecimal

Таким образом, 1,2200 напечатает 1,22, а 1,0000 напечатает 1,00.

Изменить А также вернуть 1.222200 как 1.2222 и 1.220000001 как 1.220000001 и т. д. Поэтому, игнорируя первые два нуля, я хочу обрезать все входящие 0 и не обрезать ненулевые значения

Одним из способов может быть умножение, затем применение встроенных конечных нулей обрезки, а затем деление на 100. Это может быть проблематично с крайними случаями, но значения в моей проблеме основаны на валюте и никогда не превышают границы, установленные Java (иначе это означает, что мое программное обеспечение работает с ставками, исчисляемыми миллионами долларов)

Уродливое решение выглядит следующим образом

System.out.println(((new BigDecimal("1.230223000")
                                 .multiply(new BigDecimal("100.0"))
                                 .stripTrailingZeros()).divide(new BigDecimal("100.0"))));

person geoaxis    schedule 30.05.2011    source источник
comment
обратите внимание, что ваши новые требования противоречат вашим первоначальным: как 1.230223000 можно превратить в 1.230223, но 1.0000 должно печатать 1.00?   -  person Joachim Sauer    schedule 30.05.2011
comment
нет, они не Иоахим. прочти снова. Я хочу игнорировать первые два нуля после запятой для обрезки. И вход всегда будет иметь тип не менее x.xx   -  person geoaxis    schedule 30.05.2011
comment
да, я понял это после того, как написал свой комментарий. Помогает ли мой (обновленный) ответ?   -  person Joachim Sauer    schedule 30.05.2011


Ответы (6)


Проверь это,

import java.text.DecimalFormat;
import java.text.NumberFormat;

public class DecimalFormatExample
{
  public static void main(String args[])
  {
  double amount = 2192.015;
  NumberFormat formatter = new DecimalFormat("#0.00");
  System.out.println("The Decimal Value is:"+formatter.format(amount));
  }
}  
person Max    schedule 30.05.2011
comment
Это урежет new BigDecimal("1.234"), который (согласно новым требованиям) должен быть напечатан полностью. - person Joachim Sauer; 30.05.2011

Обновление. Наличие этих смешанных требований (т. е. должно отображаться не менее 2 цифр после запятой, но столько, сколько необходимо) реализовано нетривиально, но вы можете приблизиться к этому:

Объедините stripTrailingZeros() с DecimalFormat, чтобы получить желаемое поведение (или близкое к нему):

DecimalFormat df = new DecimalFormat("0.00########")
String formatted = df.format(bigDecimal.stripTrailingZeros())

Это отформатирует любое значение BigDecimal как минимум с 2 цифрами после запятой и до 10 цифр после запятой, если это улучшит точность.

BigDecimal значений, содержащих более десяти знаков после запятой, все равно будут обрезаны:

      input      |  output
-----------------+----------
 1.20000         | 1.20
 1.23000         | 1.23
 1.2301          | 1.2301
 1.230001000     | 1.230001
 1.2300000000001 | 1.23

Исходный ответ:

Если вы всегда хотите иметь ровно 2 цифры после запятой и знаете, что таким образом не потеряете точность, вы можете вызвать setScale(2, RoundingMode.UNNECESSARY):

System.out.println(new BigDecimal("1.23000").setScale(2, RoundingMode.UNNECESSARY));

Этот код напечатает 1.23. Обратите внимание, что это вызовет ArithmeticException, когда округление будет необходимо (т.е. все, что после первых двух цифр, не равно нулю).

Если ваши значения могут иметь более высокую точность и вы хотите применить некоторое округление, просто замените RoundingMode.UNNECESSARY на подходящее значение:

System.out.println(new BigDecimal("1.2301").setScale(2, RoundingMode.CEILING));

Это напечатает 1.24.

Если вы не знаете точное количество цифр, но хотите, чтобы их было как можно меньше (т. е. вы хотите наименьшее из возможных scale для BigDecimal), вызовите stripTrailingZeros() сделает именно то, что вы хотите:

System.out.println(new BigDecimal("1.230001000").stripTrailingZeros();

Это напечатает 1.230001.

person Joachim Sauer    schedule 30.05.2011
comment
Примечание. В моем ответе предполагается, что вам нужно значение. Если вы только хотите отформатировать способ отображения значения, то ответ @Max является более подходящим. - person Joachim Sauer; 30.05.2011
comment
Мне нужно значение, и я также хочу, чтобы оно работало для следующего случая: BigDecimal 1.230002000000 возвращает BigDecimal 1.230002 - person geoaxis; 30.05.2011
comment
@geoaxis: я обновил свой ответ для этих измененных требований. - person Joachim Sauer; 30.05.2011

Этот метод даст вам желаемый результат (денежный раунд): (что такое String, потому что это лучше для BigDecimal, см. документацию)

public static float roundUp(String what, int howmuch) throws Exception{

    try {
        return (new BigDecimal(what).setScale(howmuch, BigDecimal.ROUND_UP)).floatValue();
    } catch (NumberFormatException nfe) {
        throw new Exception("BigDecimal cannot parse value : " + what, nfe);
    }
}
person EricParis16    schedule 30.05.2011

Если это для отображения, используйте:

BigDecimal d = new BigDecimal("1.2200");
NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US);
String s = n.format(d.doubleValue());
person Till    schedule 30.05.2011

Для вывода как String используйте DecimalFormat.

В противном случае используйте это:

public static BigDecimal stripToMinimumScale(BigDecimal value, 
                                             final int minimumScale) {
  if (value.scale() == minimumScale) // Already correct scale
    return value;
  else {
    value = value.stripTrailingZeros();
    return (value.scale() < minimumScale) ?  
        value.setScale(minimumScale) : // Too few decimals, needs zero pad
        value; // Do not round any significant digits
  }
}
person Mattias Jiderhamn    schedule 17.10.2012

person    schedule
comment
этот ответ уже был опубликован и не входит в сферу действия самого быстрого оружия на западе. - person Woot4Moo; 21.10.2012