Форматирование чисел с одинаковым количеством отступов

Я хочу отформатировать 3-значные поплавки на Java, чтобы они выстроились вертикально таким образом, чтобы они выглядели следующим образом:

123.45
 99
 23.2
 45

Когда я использую класс DecimalFormat, я становлюсь близко, но я хочу вставить пробелы, когда элемент имеет 1 или 2 цифры.

Мой код:

DecimalFormat formatter = new java.text.DecimalFormat("####.##");
float [] floats = [123.45, 99.0, 23.2, 45.0];

for(int i=0; i<floats.length; i++)
{
    float value = floats[i];

    println(formatter.format(value));
}

Он производит:

123.45
99
23.2
45

Как я могу напечатать его так, чтобы все, кроме первой строки, были сдвинуты на 1 пробел?

Ответ 1

Попробуйте с String.format() (JavaDoc):

public static void main(String args[]){
  String format = "%10.2f\n";  // width == 10 and 2 digits after the dot
  float [] floats = {123.45f, 99.0f, 23.2f, 45.0f};
  for(int i=0; i<floats.length; i++) {
      float value = floats[i];
      System.out.format(format, value);
}

а выход:

123.45
 99.00
 23.20
 45.00

Ответ 2

Это тривиально с заменой строки регулярного выражения.

formatter.format(f).replaceAll("\\G0", " ")

Здесь он находится в контексте: (см. также на ideone.com):

    DecimalFormat formatter = new java.text.DecimalFormat("0000.##");
    float[] floats = {
        123.45f,     //  123.45
         99.0f,      //   99
         23.2f,      //   23.2
         12.345f,    //   12.35
           .1234f,   //     .12
        010.001f,    //   10
    };

    for(float f : floats) {
        String s = formatter.format(f).replaceAll("\\G0", " ");
        System.out.println(s);
    }

Это использует DecimalFormat для большей части форматирования (нулевое дополнение, необязательный # и т.д.), а затем использует String.replaceAll(String regex, String replacement) заменить все ведущие нули на пробелы.

Образец регулярного выражения \G0. То есть 0, которому предшествует \G, который является якорем "конца предыдущего совпадения". \G также присутствует в начале строки, и это то, что позволяет привести нули (и никакие другие нули) к совпадению и заменить пробелами.

Ссылки


В escape-последовательности

Причина, по которой шаблон \G0 записывается как "\\G0" как литерал строки Java, заключается в том, что обратная косая черта является символом escape. То есть, "\\" - это строка длиной одна, содержащая обратную косую черту.

Ссылки

Связанные вопросы


Дополнительные советы

Обратите внимание, что я использовал цикл for-each, что приводит к значительно более простому коду, что повышает читаемость и минимизирует вероятность ошибок. Я также сохранил переменные с плавающей запятой как float, используя суффикс f, чтобы объявить их как float литералы (поскольку они по умолчанию double), но нужно сказать, что в целом вы должен предпочесть double в float.

См. также

Ответ 3

Просто измените свою первую строку, заменив символы "#" на "0" . Он решит вашу проблему и создаст форматированные числа с одинаковой длиной, как описано в Java API. С помощью этого метода ваши строки будут начинаться и заканчиваться дополнительными номерами "0" (например, 099,00):

DecimalFormat formatter = new java.text.DecimalFormat("0000.00");

Если вы хотите правильное выравнивание без тезисов бесполезно "0" , вам придется создать свой собственный метод форматирования: он не существует в собственном Java API.

Ответ 4

В том же духе, что и Benoit, здесь предлагается класс, расширяющий DecimalFormat, который обеспечивает заданную минимальную длину левым заполнением отформатированных чисел с пробелами. Он тестировался (Java 6, 7), более общий и обеспечивает рабочий пример.

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;

public class PaddingDecimalFormat extends DecimalFormat {
    private int minimumLength;

    /**
     * Creates a PaddingDecimalFormat using the given pattern and minimum minimumLength and the symbols for the default locale.
     */
    public PaddingDecimalFormat(String pattern, int minLength) {
        super(pattern);
        minimumLength = minLength;
    }

    /**
     * Creates a PaddingDecimalFormat using the given pattern, symbols and minimum minimumLength.
     */
    public PaddingDecimalFormat(String pattern, DecimalFormatSymbols symbols, int minLength) {
        super(pattern, symbols);
        minimumLength = minLength;
    }

    @Override
    public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
        int initLength = toAppendTo.length();
        super.format(number, toAppendTo, pos);
        return pad(toAppendTo, initLength);
    }

    @Override
    public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
        int initLength = toAppendTo.length();
        super.format(number, toAppendTo, pos);
        return pad(toAppendTo, initLength);
    }

    private StringBuffer pad(StringBuffer toAppendTo, int initLength) {
        int numLength = toAppendTo.length() - initLength;
        int padLength = minimumLength - numLength;
        if (padLength > 0) {
            StringBuffer pad = new StringBuffer(padLength);
            for(int i = 0; i < padLength; i++) {
                pad.append(' ');
            }
            toAppendTo.insert(initLength, pad);
        }
        return toAppendTo;
    }

    public static void main(String[] args) {
        PaddingDecimalFormat intFormat = new PaddingDecimalFormat("#", 6);
        for (int i = 0; i < 20; i++) {
            System.out.println(intFormat.format(i) + intFormat.format(i*i*i));
        }
    }
}

Ответ 5

Метод, который должен ответить на вашу проблему (я написал его прямо здесь и не протестировал его, чтобы вы могли исправить ошибки, но, по крайней мере, вы поняли):

public class PaddingDecimalFormat extends DecimalFormat {

    private int maxIntLength = 1;

    public PaddingDecimalFormat(String pattern) {
        super(pattern);
    }

    public void configure(Number[] numbers) {
        for(Number number : numbers) {
             maxIntLength = Math.max(maxIntLength, Integer.toString(number.intValue()).length()); 
        }
    }

    @Override
    public void format(Number number) {
        int padding = maxIntLength - Integer.toString(number.intValue()).length();

        StringBuilder sb = new StringBuilder();

        for(int i=0; i<padding; i++) {
            sb.append(' ');
        }

        sb.append(super.format(number));

        return sb.toString();
    }
}

Ответ 6

Представьте точку с запятой и System.out; форматирование, как указано выше.

printf ("   ".substring (("" + Math.round (f)).length ) + formatter.format (f))

Я бы предпочел log-10-Function, чтобы рассчитать размер 999 или от 100 до 3 вместо неявного toString-вызова, но я просто нахожу логарифм naturalis.

Math.round(987.65) дает 987.
( "+ 987).length дает 3
" ___". substring (3) - пустая строка, для короткого числа (0-9) она вернет две пробелы.