我无法理解这个问题。
即使给定了足够的精度字段,JDK 的数字格式化例程也无法打印两位数。
特别是,我不明白为什么下面程序的第二个输出行是:
b.doubleValue() => 34981.29000000000000000000000000000000000000000000000000
我相信打印的值应该是34981.29000000000087311491370201110839843750000000000000
。
你能帮我理解为什么会发生这种情况吗:
PrecisionLoser.java
import java.math.BigDecimal;
public class PrecisionLoser {
public static void main(final String[] args) {
final BigDecimal b = new BigDecimal("34981.29");
System.out.printf("b => %.50f%n", b);
System.out.printf("b.doubleValue() => %.50f%n", b.doubleValue());
System.out.printf("b.floatValue() => %.50f%n", b.floatValue());
System.out.printf("Double.MIN_VALUE => %.50f%n", Double.MIN_VALUE);
System.out.println("-");
final double d = 34981.2900000000008731149137020111083984375;
System.out.printf("d => %.50f%n", d);
System.out.printf("new BigDecimal(d) => %.50f%n", new BigDecimal(d));
System.out.printf("new BigDecimal(b.doubleValue()) => %.50f%n", new BigDecimal(b.doubleValue()));
System.out.printf("d == b.doubleValue() => %b%n", d == b.doubleValue());
final double e = 34981.29;
System.out.printf("d == e => %b%n", d == e);
System.out.println("-");
System.out.printf("Double.doubleToLongBits(b.doubleValue()) => 0x%16x%n", Double.doubleToLongBits(b.doubleValue()));
System.out.printf("Double.doubleToLongBits(d) => 0x%16x%n", Double.doubleToLongBits(d));
System.out.printf("Double.doubleToLongBits(e) => 0x%16x%n", Double.doubleToLongBits(e));
}
}
输出
$ javac PrecisionLoser.java
$ java PrecisionLoser
b => 34981.29000000000000000000000000000000000000000000000000
b.doubleValue() => 34981.29000000000000000000000000000000000000000000000000
b.floatValue() => 34981.28906250000000000000000000000000000000000000000000
Double.MIN_VALUE => 0.00000000000000000000000000000000000000000000000000
-
d => 34981.29000000000000000000000000000000000000000000000000
new BigDecimal(d) => 34981.29000000000087311491370201110839843750000000000000
new BigDecimal(b.doubleValue()) => 34981.29000000000087311491370201110839843750000000000000
d == b.doubleValue() => true
d == e => true
-
Double.doubleToLongBits(b.doubleValue()) => 0x40e114a947ae147b
Double.doubleToLongBits(d) => 0x40e114a947ae147b
Double.doubleToLongBits(e) => 0x40e114a947ae147b
最佳答案
用调试器查看转换过程,我认为发生的情况是 double 首先转换为字符串,忽略精度。然后,调整字符串以匹配指定的精度(在末尾填充 0,或通过舍入截断 - 请参阅 sun.misc.FormattedFloatingDecimal 的 applyPrecision)。
并且,原始转换似乎使用(最小?)小数位数,如果重新解析,将产生原始 double 值。
关于java - 即使精度超过可用数字,格式也不打印所有两位数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47186832/