Вопрос

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

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 Десятичный формат API?Спасибо за предложения!Я думаю, мне, возможно, придется создать подкласс Десятичный формат потому что я ограничен интерфейсом, который уже существует.

Это было полезно?

Решение

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

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

Другие советы

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

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

Не могли бы вы использовать 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) чтобы сделать это.

Редактировать:Ух ты, это PrintfFormat() вещь огромная и, кажется, ненужная:

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

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

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

if (value.compareTo (положительный) == 1 || value.compareTo (отрицательный) == -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.0E + 0 " шаблон вместо? Обратите внимание на знак плюс перед последним нулем.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top