Существует ли библиотека форматирования чисел Java, которая обрабатывает значимые цифры? - PullRequest
12 голосов
/ 29 марта 2011

Встроенный десятичный формат позволяет указывать только количество цифр справа от десятичного разряда.

Из-за ограничений представления чисел в виде двойных чисел форматирование чисел должно включать некоторый уровень округления внутриЭто.В общем случае, это округление должно быть до числа значащих цифр (регистр по умолчанию равен точности двойного), иначе ваш отформатированный двойник в итоге будет отображать такие вещи, как 3,5999999 вместо 3,6.

БлижайшийРешение, которое я смог найти, - это использование

new BigDecimal(double, new MathContext(14, RoundingMode.HALF_EVEN).stripTrailingZeros().toPlainString()

, которое обеспечивает только один формат.Если мне нужно отформатировать его вообще (разделитель группы, десятичный разделитель, ограничение на количество цифр, заполнение и т. Д.), В библиотеке JDK ничего нет.

Существует ли общая библиотека форматирования чисел, котораябудет правильно обрабатывать округление до значащих цифр?

Кто-то спросил примеры.Итак, допустим, я хотел отформатировать до 4 значащих цифр, а затем:

0.000003599999 -> 0.0000036
4.12345 -> 4.123
1234.345 -> 1234

Общий подход, который мы бы использовали, заключался в округлении до 14 цифр, поскольку в зависимости от обстоятельств двойное число может представлять только около 15-17 значащих цифр в любом случае (или так я прочитал).

Ответы [ 4 ]

10 голосов
/ 23 мая 2011

Это добавляет много накладных расходов (5 МБ или около того), но проект International Components for Unicode имеет улучшенный DecimalFormat, который прекрасно обрабатывает значимые цифры.

http://icu -project.org /apiref / icu4j / com / ibm / icu / text / DecimalFormat.html # sigdig

DecimalFormat formatter = new DecimalFormat();
formatter.setMaximumSignificantDigits( 4 );
System.out.println( formatter.format( hoursSinceLastAccident ) );
3 голосов
/ 07 августа 2014

Стоит отметить, что если речь идет именно о Android , а не о Java, на который нацелено, встроенный DecimalFormat поддерживает форматирование значимых цифр с помощью символа @.

String smallPi = new DecimalFormat("@@@").format("3.14159"); // formats number as '3.14'
2 голосов
/ 30 марта 2011

Как насчет такого решения:

double l = 34563.35129854289;
short offset = (short) Math.ceil(Math.log10(l) + 1);
short significantDigits = 10;

System.out.printf("%,." + (significantDigits - offset) + "f", l);
//String output = String.format("%,." + (significantDigits - offset) + "f", l);

Вывод:

34 563,3513 (т. Е. ',' В printf указывает на использование разделителя групп)

0 голосов
/ 22 октября 2013

Я нашел этот хороший способ сделать это.

Это если вы просто хотите распечатать его.

public String toSignificantFiguresString(BigDecimal bd, int significantFigures){
    return String.format("%."+significantFigures+"G", bd);
}

Это если вы хотите конвертировать:

public BigDecimal toSignificantFigures(BigDecimal bd, int significantFigures){
    String s = String.format("%."+significantFigures+"G", bd);
    BigDecimal result = new BigDecimal(s);
    return result;
}

Вот пример этого в действии:

    BigDecimal bd2 = toSignificantFigures(BigDecimal.valueOf(4.12345), 4);
    BigDecimal bd3 = toSignificantFigures(BigDecimal.valueOf(1234.345), 4);
    BigDecimal bd4 = toSignificantFigures(BigDecimal.valueOf(0.000003599999), 4);

    System.out.println("bd2: " + String.format("%f",bd2));
    System.out.println("bd3: " + String.format("%f",bd3));
    System.out.println("bd4: " + String.format("%f",bd4));
...