Java结果因(int)Math.pow(2,x)和1 <1而不同。

时间:2012-05-02 15:19:20

标签: java bitwise-operators bit-shift

为什么以下两个操作在x = 3132的Java中产生不同的结果,但x=3的结果相同?

int x=3;
int b = (int) Math.pow(2,x);
int c = 1<<x;

结果:

x=32: b=2147483647; c=1;
x=31: b=2147483647; c=-2147483648;
x=3:  b=8         ; c=8

5 个答案:

答案 0 :(得分:18)

有多个问题在起作用:

此采访问题的作用表明(int)Math.pow(2, x)1 << xx ... 0范围之外的30值不相等。

P.S。或许有趣的是,使用long代替int(和1L代替1)会给出另一组与其他两个不同的结果。即使最终结果转换为int,这也成立。

答案 1 :(得分:3)

根据文档Math.pow将它的两个参数提升为double并返回double。显然当返回的结果是double并且你将它转换为int时,你将只得到最高的32位,其余的将被截断 - 因此你总是得到(int) Math.pow(2,x);值。当你进行bitshift时,你总是使用整数,因此会发生溢出。

答案 2 :(得分:2)

考虑int类型的限制。它能保持多大的数量?

答案 3 :(得分:0)

int的大小为32位,由于它是有符号的(默认情况下),因此第一位用于符号。向左移31位时,得到Two's Compliment,即 - (2 ^ 32)。当你向左移动32位时,它只是一直循环回到1.如果你用long而不是int进行移位,你会得到你期望的答案(直到你移动63+位)。 / p>

答案 4 :(得分:0)

这是一个长期案例的微观基准。在我的笔记本电脑(2.8GHz)上,使用shift代替Math.pow的速度提高了7倍。

int limit = 50_000_000;
@Test
public void testPower() {
    Random r = new Random(7);
    long t = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
        int p = r.nextInt(63);
        long l = (long)Math.pow(2,p);
    }
    long t1 = System.currentTimeMillis();
    System.out.println((t1-t)/1000.0); // 3.758 s
}
@Test
public void testShift() {
    Random r = new Random(7);
    long t = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
        int p = r.nextInt(63);
        long l = 1L << p;
    }
    long t1 = System.currentTimeMillis();
    System.out.println((t1-t)/1000.0); // 0.523 s
}