Pregunta

Estoy usando Java DecimalFormat clase para imprimir números en notación científica. Sin embargo, hay un problema que tengo. Necesito que las cuerdas sean de longitud fija independientemente del valor, y el signo en el poder de diez lo está arrojando. Actualmente, así es como se ve mi formato:

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

Esto me da las siguientes combinaciones: 1.0E1, 1.0E-1, -1.0E1 y -1.0E-1.

Puedo usar setPositivePrefix para obtener: + 1.0E1, + 1.0E-1, -1.0E1 y -1.0E-1, o lo que quiera, pero no afecta el signo del poder!

¿Hay alguna forma de hacer esto para que pueda tener cadenas de longitud fija? Gracias!

Editar: Ah, ¿entonces no hay forma de hacerlo usando la API DecimalFormat existente de Java? Gracias por las sugerencias! Creo que debo tener que subclasificar DecimalFormat porque estoy limitado por la interfaz que ya está en su lugar.

¿Fue útil?

Solución

Aquí hay una manera. Hokey, tal vez, pero funciona ...

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

Alternativamente, podría subclase DecimalFormat, pero generalmente me parece más limpio no subclasificar de clases concretas.

Otros consejos

Esto funcionó para mí,

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

¿Podría usar printf () en su lugar:

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

Salida:

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

Si necesita generar un String en su lugar, puede usar la información proporcionada en Impresión formateada para Java (sprintf) para hacer eso.

EDITAR: Wow, esa cosa PrintfFormat () es enorme y parece innecesaria:

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

Se me ocurrió la idea del código anterior de Obtenga un OutputStream en una cadena .

¿Cómo usarlo?
Consulte el método formatTest .

if (value.compareTo (positivo) == 1 || value.compareTo (negativo) == -1) es útil para números muy grandes

/**
 * 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("----------");
}

¿Por qué no usar " 0.0E + 0 " patrón en su lugar? Tenga en cuenta el signo más antes del último cero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top