如果您通过减少第三位小数对输入进行排序并将所有内容向下四舍五入,您将引入最小的绝对舍入误差 - 同时保持总和不变。
举个简单的例子:
输入
0.132, 0.226, 0.257, 0.385 // sums up to 1.00
按小数点后第三位(降序)
0.257, 0.226, 0.385, 0.132
四舍五入
0.25, 0.22, 0.38, 0.13 // sums up to 0.98
四舍五入刚好可以达到整数
0.26, 0.23, 0.38, 0.13 // sums up to 1.00
在代码中(未经测试):
public void printRounded(double[] ds) {
// create wrapper objects
int n = ds.length;
Wrapper[] ws = new Wrapper[n];
for (int i = 0; i < n; i++)
ws[i] = new Wrapper(i, (int)(ds[i] * 1000) % 10, (int)(ds[i] * 100));
// sort by third decimal, descending
Arrays.sort(ws, new Comparator<Wrapper>() {
public int compare(Wrapper o1, Wrapper o2) {
return o2.thirdDecimal.compareTo(o1.thirdDecimal);
}
});
// find number of elements that must be rounded up and increment
int sum = 0;
for (int i = 0; i < n; i++)
sum += ws[i].prefix;
int numberToIncrement = 100 - (sum % 100);
for (int i = 0; i < numberToIncrement ; i++)
ws[i].prefix++;
// sort back to input order
Arrays.sort(ws, new Comparator<Wrapper>() {
public int compare(Wrapper o1, Wrapper o2) {
return o1.index.compareTo(o2.index);
}
});
// print values
for (int i = 0; i < n; i++) {
System.out.println(ws[i].prefix / 100 + "." ws[i].prefix % 100);
}
}
private class Wrapper {
public Wrapper(int index, int thirdDecimal, int prefix) {
this.index = index;
this.thirdDecimal = thirdDecimal;
this.prefix = prefix;
}
public int index;
public int thirdDecimal;
public int prefix;
}
您当然可以将整数转换回双精度并使用标准格式,而不是使用自定义格式。