I'm using Java's DecimalFormat class to print out numbers in Scientific Notation. However, there is one problem that I have. I need the strings to be of fixed length regardless of the value, and the sign on the power of ten is throwing it off. Currently, this is what my format looks like:
DecimalFormat format = new DecimalFormat("0.0E0");
This gives me the following combinations: 1.0E1, 1.0E-1, -1.0E1, and -1.0E-1.
I can use setPositivePrefix to get: +1.0E1, +1.0E-1, -1.0E1, and -1.0E-1, or whatever I like, but it doesn't affect the sign of the power!
Is there any way to do this so that I can have fixed length strings? Thanks!
Edit: Ah, so there's no way to do it using Java's existing DecimalFormat API? Thanks for the suggestions! I think I may have to subclass DecimalFormat because I am limited by the interface that is already in place.
Here's one way. Hokey, perhaps, but it works...
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));
}
}
Alternatively you could subclass DecimalFormat, but I find it generally cleaner not to subclass from concrete classes.
This worked form me,
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);
Could you use printf()
instead:
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);
Output:
1.0E-2
1.0E-02
1.0E2
1.0E+02
If you need to output to a String
instead, you can use the information provided at Formatted Printing for Java (sprintf) to do that.
EDIT: Wow, that PrintfFormat()
thing is huge and seems to be unnecessary:
OutputStream b = new ByteArrayOutputStream();
PrintStream p = new PrintStream(b);
p.printf("%1.1E", d);
System.out.println(b.toString());
I got the idea for the above code from Get an OutputStream into a String.
How to use?
See formatTest
method.
if (value.compareTo(positive) == 1 || value.compareTo(negative) == -1)
is useful for very large numbers
/**
* 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("----------");
}
Why not use "0.0E+0" pattern instead? Note the plus sign before last zero.
来源:https://stackoverflow.com/questions/1213747/java-decimalformat-scientific-notation-question