如果您想避免使用格式化,您可以在打印之前将结果四舍五入到一个固定的精度,并利用 Java 会进行少量四舍五入来隐藏表示错误的事实。
例如到小数点后 6 位
public static double round6(double d) {
return Math.round(d * 1e6) / 1e6;
}
round()
和的结果1e6
可以精确表示。此外,“ IEEE 754要求正确舍入:也就是说,舍入结果就像使用无限精确算术来计算值然后舍入一样” 剩下的唯一错误是表示错误,因为它采用最接近的可表示值。Java 的 toString() 假设当您有一个具有较短小数的最接近的可表示值的双精度数时,这就是您想要看到的。
例如 0.1 的实际值是
System.out.println(new BigDecimal(0.1));
印刷
0.1000000000000000055511151231257827021181583404541015625
但是当 Double.toString() 被传递这个值时,它确定 0.1 将被转换为这个双精度,所以这就是它应该显示的内容。
顺便说一句,在 Java 6 中有一个错误,它不使用最小位数。
for (int i = 1; i <= 9; i++)
System.out.print(i / 1000.0 + " ");
在 Java 6 中打印
0.0010 0.0020 0.0030 0.0040 0.0050 0.0060 0.0070 0.0080 0.0090
并在 Java 7 中打印
0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009
如果性能不重要,我经常使用 printf,如果是,我使用自定义例程将双精度写入直接 ByteBuffer 到固定精度(有效地舍入它)这更快,因为它不创建任何对象。
我还想避免在结果为 1.1234567891234567 或 1.33333333333333 的情况下丢失数据,在这些情况下结果应该保持不变。
在这种情况下,不要对结果进行四舍五入,直到需要显示它们。