Java 使用相同的填充量格式化数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3339516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:25:36  来源:igfitidea点击:

Formatting numbers with same amount of padding

java

提问by sarasota

I want to format 3 digit floats in Java so they line up vertically such that they look like:

我想在 Java 中格式化 3 位浮点数,以便它们垂直排列,使其看起来像:

123.45
 99
 23.2
 45

When I use DecimalFormat class, I get close, but I want to insert spaces when the item has 1 or 2 digits.

当我使用 DecimalFormat 类时,我很接近,但我想在项目有 1 或 2 位数字时插入空格。

My code:

我的代码:

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

It produces:

它产生:

123.45
99
23.2
45

How can I print it so that all but the first line is shifted over by 1 space?

如何打印它以便除第一行之外的所有行都移动 1 个空格?

回答by Benoit Courtine

Just change your first line, replacing '#' characters by '0'. It will solve your problem and produce formatted numbers with the same length, as explicated in the Java API. With that method, your lines will start and end with additional '0' numbers (099.00 for example) :

只需更改您的第一行,将 '#' 字符替换为 '0'。它将解决您的问题并生成具有相同长度的格式化数字,如Java API 中所述。使用该方法,您的行将以附加的“0”数字开头和结尾(例如 099.00):

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

If you want a correct alignment without theses useless '0', you'll have to create your own formatting method : it doesn't exist in the native Java API.

如果你想要一个没有这些无用的“0”的正确对齐,你必须创建你自己的格式化方法:它在本机 Java API 中不存在。

回答by Benoit Courtine

A method that should answer your problem (I wrote it directly here and did not tested it so you could have some bugs to correct, but at least, you get the idea) :

一种应该可以解决您的问题的方法(我直接在此处编写并没有对其进行测试,因此您可以纠正一些错误,但至少,您明白了):

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

回答by RealHowTo

Try with String.format()(JavaDoc):

尝试使用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);
}

and the output is :

输出是:

123.45
 99.00
 23.20
 45.00

回答by polygenelubricants

This is trivial with a bit of regular expression string replacement.

这对于一些正则表达式字符串替换来说是微不足道的。

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

Here it is in context: (see also on ideone.com):

这是上下文:(另请参见 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);
    }

This uses DecimalFormatto do most of the formatting (the zero padding, the optional #, etc) and then uses String.replaceAll(String regex, String replacement)to replace all leading zeroes to spaces.

这用于DecimalFormat执行大部分格式(零填充、可选#等),然后用于String.replaceAll(String regex, String replacement)将所有前导零替换为空格。

The regex pattern is \G0. That is, 0that is preceded by \G, which is the "end of previous match" anchor. The \Gis also present at the beginning of the string, and this is what allows leading zeroes (and no other zeroes) to be matched and replaced with spaces.

正则表达式模式是\G0. 也就是说,0前面是\G,这是“上一场比赛的结束”锚点。该\G也出现在字符串的开头,这是什么让前导零(并且没有其他零)进行匹配,并用空格代替。

References

参考



On escape sequences

关于转义序列

The reason why the pattern \G0is written as "\\G0"as a Java string literal is because the backslash is an escape character. That is, "\\"is a string of length one, containing the backslash.

将模式\G0写为"\\G0"Java 字符串文字的原因是反斜杠是转义字符。也就是说,"\\"是一个长度为 1 的字符串,包含反斜杠。

References

参考

Related questions

相关问题



Additional tips

其他提示

Note that I've used the for-eachloop, which results in a much simpler code, thus enhancing readability and minimizing chances of mistakes. I've also kept the floating point variables as float, using the fsuffix to declare them as floatliterals (since they're doubleby default otherwise), but it needs to be said that generally you should prefer doubleto float.

请注意,我使用了for-each循环,这会产生更简单的代码,从而提高可读性并最大程度地减少出错的机会。我也不停的浮点变量float,使用f后缀为它们申报为float文本(因为他们是double在默认情况下以其他方式),但它需要说,通常,你应该更喜欢doublefloat

See also

也可以看看

回答by user unknown

Imagine semicolon and System.out.; formatter like above in question.

想象一下分号和 System.out。如上所述的格式化程序。

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

I would prefer a log-10-Function, to calculate the size of 999 or 100 to 3, instead of the implicit toString-call, but I just find logarithm naturalis.

我更喜欢使用 log-10-Function 来计算 999 或 100 到 3 的大小,而不是隐式的 toString 调用,但我只是找到了自然对数。

Math.round (987.65) gives 987.
("" + 987).length gives 3
"___".substring (3) is the empty string, for a short number (0-9) it will return two blanks.

Math.round (987.65) 给出 987.
("" + 987).length 给出 3
"___".substring (3) 是空字符串,对于短数 (0-9) 它将返回两个空格。

回答by Oliver Coleman

In the same vein as Benoit's answer, here's a class extending DecimalFormat which ensures a specified minimum length by left-padding formatted numbers with spaces. It's tested (Java 6, 7), more general and provides a working example.

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