【问题标题】:BigDecimal Class in Java - Reason behind Constant valuesJava 中的 BigDecimal 类 - 常量值背后的原因
【发布时间】: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 &amp; 运算符。

我希望我的问题很清楚。衷心感谢您的耐心等待。

【问题讨论】:

  • Q1 : 假设这段代码来自 BigDecimal 的构造函数,这段代码正在解码值的char[] 表示。因此基数为 10。
  • Q3 : valBits 很长,因此以 64 位表示。所以 valBits >> 63 给出第 64 位,即符号位。
  • Q1 因为它是小数。 Q2-4 因为它正在解码 double.

标签: java operators


【解决方案1】:

Q1:当然,基数是计算的基础。您正在使用以 10 为基数的数字;)

Q4:7ff 二进制:0111 1111 1111

如果您阅读位移运算符的说明,Java "Bit Shifting" Tutorial? 您会看到 >> 63 丢弃了前 63 位并保留最后一位。最后一位是符号位(用于有符号类型)。如果为 1,则整数为负数,因此此处为 int 符号。

另外,浮点的定义可以参考https://en.wikipedia.org/wiki/Floating_point。 52是为了区分指数和有效数。

Q4:当然,对于指数,您不想在其中使用“符号”位,因为它不是指数的一部分,因此掩码为 7ff。 Bitwise & 0x7ff 就是这样做的;它只会在第一位放一个 0,而让另一个保持相同的状态。 (见'AND'运算符真值表https://en.wikipedia.org/wiki/Truth_table

编辑:

Q4 互补:如果指数是例如 12,那么第一位将是这样的:

0000 0000 1100 ... (positive value) (ex: 1x10^12)
1000 0000 1100 ... (negative value) (ex: -1x10^12)

但是:1000 0000 1100 是十进制的 2060。

如果你使用“面具”:

  1000 0000 1100 & 0111 1111 1111 -> 0000 0000 1100 (12 decimal)
  AND
  0000 0000 1100 & 0111 1111 1111 -> 0000 0000 1100 (12 decimal)

这就是 0x7ff 的用途。

【讨论】:

  • 能否请您进一步简要介绍您对 Q4 的回答。比如,为什么要使用那个特定的十六进制。?
猜你喜欢
  • 2013-09-09
  • 2021-10-21
  • 2018-06-07
  • 1970-01-01
  • 2014-10-17
  • 2011-01-31
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多