Java DecimalFormat Научная нотация Вопрос - PullRequest
5 голосов
/ 31 июля 2009

Я использую класс Java DecimalFormat для распечатки чисел в научной нотации. Однако у меня есть одна проблема. Мне нужно, чтобы строки были фиксированной длины, независимо от значения, и знак силы десяти отбрасывает их. В настоящее время мой формат выглядит так:

DecimalFormat format = new DecimalFormat("0.0E0");

Это дает мне следующие комбинации: 1.0E1, 1.0E-1, -1.0E1 и -1.0E-1.

Я могу использовать setPositivePrefix , чтобы получить: + 1.0E1, + 1.0E-1, -1.0E1 и -1.0E-1 или что угодно, но это не влияет на знак силы!

Есть ли способ сделать это, чтобы я мог иметь строки фиксированной длины? Спасибо!

Редактировать: А, значит, нет способа сделать это с помощью существующего Java DecimalFormat API? Спасибо за предложения! Я думаю, что мне, возможно, придется создать подкласс DecimalFormat , потому что я ограничен уже имеющимся интерфейсом.

Ответы [ 5 ]

6 голосов
/ 25 октября 2012

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

DecimalFormatSymbols SYMBOLS = DecimalFormatSymbols.getInstance(Locale.US);

    if (value > 1 || value < -1) {
        SYMBOLS.setExponentSeparator("e+");
    } else {
        SYMBOLS.setExponentSeparator("e");
    }

    DecimalFormat format = new DecimalFormat(sb.toString(), SYMBOLS);
3 голосов
/ 31 июля 2009

Не могли бы вы использовать printf() вместо:

Format format = new DecimalFormat("0.0E0");
Double d = new Double(.01);
System.out.println(format.format(d));
System.out.printf("%1.1E\n", d);
d = new Double(100);
System.out.println(format.format(d));
System.out.printf("%1.1E\n", d);

Выход:

1.0E-2
1.0E-02
1.0E2
1.0E+02

Если вместо этого вам необходимо вывести на String, вы можете использовать информацию, предоставленную в Форматированная печать для Java (sprintf) , чтобы сделать это.

РЕДАКТИРОВАТЬ: Wow, что PrintfFormat() вещь огромна и, кажется, не нужно:

OutputStream b = new ByteArrayOutputStream();
PrintStream p = new PrintStream(b);
p.printf("%1.1E", d);
System.out.println(b.toString());

Я получил идею для приведенного выше кода из Получить OutputStream в строку .

2 голосов
/ 31 июля 2009

Вот один из способов. Хоккей, возможно, но это работает ...

public class DecimalFormatTest extends TestCase {
    private static class MyFormat extends NumberFormat {
        private final DecimalFormat decimal;

        public MyFormat(String pattern) {
            decimal = new DecimalFormat(pattern);
        }

        public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
            StringBuffer sb = new StringBuffer();
            sb.append(modified(Math.abs(number) > 1.0, decimal.format(number, toAppendTo, pos).toString()));
            return sb;
        }

        private String modified(boolean large, String s) {
            return large ? s.replace("E", "E+") : s;
        }

        public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
            StringBuffer sb = new StringBuffer();
            sb.append(modified(true, decimal.format(number, toAppendTo, pos).toString()));
            return sb;
        }

        public Number parse(String source, ParsePosition parsePosition) {
            return decimal.parse(source, parsePosition);
        }

        public void setPositivePrefix(String newValue) {
            decimal.setPositivePrefix(newValue);
        }
    }
    private MyFormat    format;

    protected void setUp() throws Exception {
        format = new MyFormat("0.0E0");
        format.setPositivePrefix("+");
    }

    public void testPositiveLargeNumber() throws Exception {
        assertEquals("+1.0E+2", format.format(100.0));
    }

    public void testPositiveSmallNumber() throws Exception {
        assertEquals("+1.0E-2", format.format(0.01));
    }

    public void testNegativeLargeNumber() throws Exception {
        assertEquals("-1.0E+2", format.format(-100.0));
    }

    public void testNegativeSmallNumber() throws Exception {
        assertEquals("-1.0E-2", format.format(-0.01));
    }
}

В качестве альтернативы вы могли бы подкласс DecimalFormat, но я считаю, что в целом он более чист, чтобы не создавать подклассы из конкретных классов.

0 голосов
/ 01 марта 2018

Как пользоваться?
См. formatTest метод.

if (value.compareTo(positive) == 1 || value.compareTo(negative) == -1) полезно для очень больших чисел

/**
 * inspired by:<br>
 * https://stackoverflow.com/a/13065493/8356718
 * https://stackoverflow.com/a/18027214/8356718
 * https://stackoverflow.com/a/25794946/8356718
 */
public static String format(String number, int scale) {
    BigDecimal value = new BigDecimal(number);
    DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.US);
    BigDecimal positive = new BigDecimal(1);// scale is zero
    positive.setScale(0);// unnecessary
    BigDecimal negative = new BigDecimal(-1);// scale is zero
    negative.setScale(0);// unnecessary
    if (value.compareTo(positive) == 1 || value.compareTo(negative) == -1) {
        symbols.setExponentSeparator("e+");
    } else {
        symbols.setExponentSeparator("e");
    }
    DecimalFormat formatter = new DecimalFormat("0.0E0", symbols);
    formatter.setRoundingMode(RoundingMode.HALF_UP);
    formatter.setMinimumFractionDigits(scale);
    return formatter.format(value);
}

/**
 * set the scale automatically
 */
public static String format(String number) {
    BigDecimal value = new BigDecimal(number);
    return format(number, value.scale() > 0 ? value.precision() : value.scale());
}

/*
output:
----------
0e0
1.0e-2
-1.0e-2
1.234560e-5
-1.234560e-5
1e0
-1e0
3e+0
-3e+0
2e+2
-2e+2
----------
0.0000000000e0
1.0000000000e-2
-1.0000000000e-2
1.2345600000e-5
-1.2345600000e-5
1.0000000000e0
-1.0000000000e0
3.0000000000e+0
-3.0000000000e+0
2.0000000000e+2
-2.0000000000e+2
----------
*/
public static void formatTest() {
    System.out.println("----------");
    System.out.println(format("0"));
    System.out.println(format("0.01"));
    System.out.println(format("-0.01"));
    System.out.println(format("0.0000123456"));
    System.out.println(format("-0.0000123456"));
    System.out.println(format("1"));
    System.out.println(format("-1"));
    System.out.println(format("3"));
    System.out.println(format("-3"));
    System.out.println(format("200"));
    System.out.println(format("-200"));
    System.out.println("----------");
    System.out.println(format("0", 10));
    System.out.println(format("0.01", 10));
    System.out.println(format("-0.01", 10));
    System.out.println(format("0.0000123456", 10));
    System.out.println(format("-0.0000123456", 10));
    System.out.println(format("1", 10));
    System.out.println(format("-1", 10));
    System.out.println(format("3", 10));
    System.out.println(format("-3", 10));
    System.out.println(format("200", 10));
    System.out.println(format("-200", 10));
    System.out.println("----------");
}
0 голосов
/ 02 июля 2013

Почему бы вместо этого не использовать паттерн "0.0E + 0"? Обратите внимание на знак плюс перед последним нулем.

...