【发布时间】:2015-07-22 12:35:36
【问题描述】:
我正在解决 Java Puzzlers 第二个谜题。
public class Change {
public static void main(String args[]) {
System.out.println(2.00 - 1.10);
}
}
你会认为答案是 0.9。但事实并非如此。如果你锻炼这个,你会得到 0.8999999。给出的解决方案是
System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));
现在它将打印 0.9。我明白为什么它会打印 0.89999。但是虽然 我好奇地调试 BigDecimal 类,我发现在大多数地方都有很多常量值被替换。我将在下面列出所有这些,并有兴趣了解其背后的原因。
BigDecimal.java第 394 行,
while (len > 10 && Character.digit(c, 10) == 0) {
offset++;
c = in[offset];
len--;
}
这里是Character.digit(c,10)。
public static int digit(char ch, int radix) {
return digit((int)ch, radix);
}
这里 10 作为基数传递。
Q1。为什么10通过那里。??
BigDecimal.java 行号 732
int sign = ((valBits >> 63)==0 ? 1 : -1);
int exponent = (int) ((valBits >> 52) & 0x7ffL);
long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
: (valBits & ((1L<<52) - 1)) | (1L<<52));
exponent -= 1075;
第二季度。如果你深入研究代码,你可以理解 valBits 是什么,我无法理解为什么在某些地方使用 rightshift?
第三季度。在这里,您还可以看到使用了许多常量,例如 63、52。为什么?
第四季度。我可以理解这里使用的十六进制0x7ffL会提高执行速度。再次说明为什么在这里使用带有十六进制常量的 BitWise & 运算符。
我希望我的问题很清楚。衷心感谢您的耐心等待。
【问题讨论】:
-
Q1 : 假设这段代码来自 BigDecimal 的构造函数,这段代码正在解码值的
char[]表示。因此基数为 10。 -
Q3 : valBits 很长,因此以 64 位表示。所以 valBits >> 63 给出第 64 位,即符号位。
-
Q1 因为它是小数。 Q2-4 因为它正在解码
double.