我想将Java中的BigDecimal格式化为8个字符(包括分隔符),舍入HALF-UP。 一些例子:
12345.6789 -> "12345.68"
123 -> " 123.0"
0.12345678 -> "0.123457"
1.5 -> " 1.5"
0.0045 -> " 0.0045"
12 -> " 12.0"
结果必须有前导空格,最多可填充8个字符。 什么是最简单的方法?
答案 0 :(得分:2)
我很确定这不是最好的方式,但它是单向的。
首先请注意,如果您的号码在该时段之前超过六位数,或者通常在该时段之前超过width - 2
位数,则.0
的格式将不再有效。
String.format()
使用了一半作为舍入方法,因此您可以将其用作第一步,将输出设置为八个字符。
BigDecimal b = new BigDecimal(0.0045);
String format = "%8f";
String str = String.format(format, b);
输出:
12345.678900
123.000000
0.123457
1.500000
0.004500
12.000000
123456.000000
默认情况下String.format()
使用BigDecimal
的精度为6。要获得自定义精度,您需要知道周期之前有多少位数,并从总宽度中减去此数字(周期本身为+ 1)。
width - digits - 1
要获得位数,您只需检查(number % radix) == number
是否适用于radix = 10,100,1000,......只要它适合您就知道数字位数。
public static int digitsBeforePeriod(BigDecimal b) {
int number = b.intValue();
int radix = 10;
int digits = 1;
while((number % radix) != number) {
radix *= 10;
++digits;
}
return digits;
}
所以下一步是修改格式:
BigDecimal b = new BigDecimal(0.0045);
int digits = digitsBeforePeriod(b);
String format = "%8." + (8 - digits - 1) + "f";
String str = String.format(format, b);
输出:
12345.68
123.0000
0.123457
1.500000
0.004500
12.00000
123456.0
仍然有很多0,但现在至少四舍五入是正确的。现在指定如果一个数字是一个整数,你想要用.0
后缀打印,否则不打印。
为了实现这一点,可能还存在聪明的格式,但我没有想到更多。这种天真的方式很简单:
while(str.endsWith("0") && !str.endsWith(".0")) {
str = str.substring(0, str.length()-1);
}
这将删除字符串的最后一个字符,直到字符串完全没有以0
结尾或以.0
结尾。
现在数字格式正确,但未正确对齐:
12345.68
123.0
0.123457
1.5
0.0045
12.0
123456.0
要对齐它们,只需再次使用String.format()
。
str = String.format("%" + width + "s", str);
输出:
12345.68
123.0
0.123457
1.5
0.0045
12.0
123456.0
在上下文中,这看起来如下所示。请注意,我是否包含了一个检查数字,否则数字可以格式化 - 如果不是,它将打印无效。你当然也可以只打印数字,我只是想表明这种格式的局限性。
public static String trimToWidth(BigDecimal b, int width) {
String str = "Invalid";
int digits = digitsBeforePeriod(b);
// -2 for period and 0
if(digits <= width - 2) {
// use width and (width - digits - 1) as precision (-1 for period)
String format = "%" + width + "." + (width - digits - 1) + "f";
// rounds half-up
str = String.format(format, b);
// trim trailing 0s, unless it's .0
while(str.endsWith("0") && !str.endsWith(".0")) {
str = str.substring(0, str.length()-1);
}
}
// add spaces in front
str = String.format("%" + width + "s", str);
return str;
}
public static int digitsBeforePeriod(BigDecimal b) {
int number = b.intValue();
int radix = 10;
int d = 1;
while((number % radix) != number) {
radix *= 10;
++d;
}
return d;
}
public static void main(String[] args) {
double[] values = new double[] {
12345.6789, 123, 0.12345678,
1.5, 0.0045, 12, 123456, 1234567
};
BigDecimal[] bigs = new BigDecimal[values.length];
for(int i = 0; i < bigs.length; ++i) {
bigs[i] = new BigDecimal(values[i]);
System.out.println(trimToWidth(bigs[i], 8));
}
}