Обрезать более двух конечных нулей в BigDecimal

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

таким образом, 1.2200 будет печатать 1.22 и 1.0000 будет печатать 1.00

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

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

уродливое решение как folows

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

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

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

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

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

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

BigDecimal значения больше чем 10 чисел после десятичной запятой все еще будут отрезаны:

      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 когда округление будет необходимо (т. е. что-либо после первых 2 цифр не равно нулю).

если ваши значения могут иметь более высокую точность, и вы хотите применить некоторое округление, просто замените 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.


этот метод даст вам результат, который вы хотите (денежный раунд): (что такое 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);
    }
}

Если это для отображения назначения:

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

для вывода Как 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
  }
}

BigDecimal d = new BigDecimal("59.0000");
String d1 = new DecimalFormat().format(d);
System.out.println("d1 is " + d1);