Java DecimalFormat creates error when enforcing ex

2019-07-18 01:37发布

问题:

In Java, I am trying to get DecimalFormat to enforce the sign on an exponent sign. When it is positive I need a plus sign to appear. From what I have read this seems like a no brainer, but for myself it always throws up an error. I appreciate that there may be other methods to achieve my goal, but I would like to understand why in this specific method the error is occurring.

Double result = 123.456;
String sresult;

//This works
NumberFormat formatter = new DecimalFormat("0.00000E00");
        sresult = formatter.format(result); 
        System.out.println(sresult);        //1.23456E02

//This doesn't work
formatter = new DecimalFormat("0.00000E+00"); //Want to enforce the sign to appear
        sresult = formatter.format(result); 
        System.out.println(sresult);        //Expected 1.23456E+02 but error occurs

The error which is thrown up:

Exception in thread "main" java.lang.IllegalArgumentException:
Malformed exponential pattern "0.00000E+00"
    at java.text.DecimalFormat.applyPattern(Unknown Source)
    at java.text.DecimalFormat.(Unknown Source)
    at deccheck.main(deccheck.java:13)

I appreciate any insight. Thanks, Mark

回答1:

Easy way:

formatter = new DecimalFormat("0.00000E00"); // Want to enforce the sign to appear
sresult = formatter.format(result);
if (!sresult.contains("E-")) { //don't blast a negative sign
    sresult = sresult.replace("E", "E+");
}
System.out.println(sresult);

Outputs 1.23456E+02 for your example.

But I don't believe there's a way to do it from inside the DecimalFormat pattern. Or at least the javadoc doesn't indicate there is one.

Edit: trashgod brings up a good point. You'd probably want to get positive and negative signs from DecimalFormatSymbols if you plan on localizing this to different regions.

Edit 2: Andrei pointed out that E is also a localization variable. Shows what I know about localization.



回答2:

I would like to extend the solution by j flemm. The "E" and "-" are no constants, they can be set as DecimalFormatSymbols. Therefore the substitutions must respect this:

public static String hoola(final String s, final DecimalFormatSymbols symbols) {
    String result;
    final String expo = symbols.getExponentSeparator();
    final char minus = symbols.getMinusSign();
    if (!s.contains(expo + minus)) { // don't blast a negative sign
    result = s.replace(expo, expo + '+');
    } else {result=s;}
    return result;
}

/**
 * @param args
 */
public static void main(final String[] args) {
    final DecimalFormat decForm = (DecimalFormat) NumberFormat
            .getInstance(Locale.GERMAN);
    final DecimalFormatSymbols newSymbols = new DecimalFormatSymbols(
            Locale.GERMAN);
    newSymbols.setExponentSeparator("*10^");
    newSymbols.setMinusSign('\u2212');
    decForm.setDecimalFormatSymbols(newSymbols);
    decForm.applyPattern("0.00000E00");
    System.out.println(hoola(decForm.format(1234.567), decForm
            .getDecimalFormatSymbols()));
    System.out.println(hoola(decForm.format(000.00567), decForm
            .getDecimalFormatSymbols()));
}

Result is:

  • 1,23457*10^+03
  • 5,67000*10^−03


回答3:

I don't think the '+' character is an accepted character in a pattern (after studying the javadocs). And the pattern for for the exponential part si described as:

 Exponent:
         E MinimumExponent
 MinimumExponent:
         0 MinimumExponent(opt)

If you add anything there it will confuse the parser. I think your only option is to give it the normal pattern (without '+') and then get the String and use regex to add the '+' there.

sresult = formatter.format(result);
sresult = sresult.replaceAll("E([^\\-]+)", "E+$1");

The best option might be extending DecimalFormat and doing this in the overwritten format method



回答4:

@j flemm's approach is appealing because "Negative exponents are formatted using the localized minus sign, not the prefix and suffix from the pattern."—DecimalFormat.