Java DecimalFormat Вопрос о научной нотации
-
06-07-2019 - |
Вопрос
Я использую 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 " шаблон вместо? Обратите внимание на знак плюс перед последним нулем.