爪哇结果不同对(INT)Math.pow(2,x)和1 << X(Java result

2019-07-29 05:54发布

为什么下面两个步骤:在Java中产生不同的结果为x = 3132 ,但在相同的结果, 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

Answer 1:

有在作怪多个问题:

  • 一个int只能存储之间的值-21474836482147483647
  • 1 << x只使用的最低五个比特x 。 因此, 1 << 32是由定义相同1 << 0
  • 移位操作所执行的左操作数的值的二进制补码整数表示 ; 这就解释了为什么1 << 31为负。
  • Math.pow(2, 32)返回一个double
  • (int)(d)其中d是一个double大于2147483647返回2147483647 ( “类型的可表示的最大值int ” )。

这是什么面试问题确实是表明(int)Math.pow(2, x)1 << x不等价的值x外部0 ... 30范围内。

PS这也许是有趣的是,使用long代替int (和1L代替1 )将给予另一套结果与其它两个不同的。 这适用即使最终结果转换为int



Answer 2:

根据该文件Math.pow同时促进其参数将翻一番,双倍返还。 显然,当返回的结果是双,你将它转换成int,你只会得到最高的32位,其余的将被截断-因此你总是得到(int) Math.pow(2,x); 值。 当你位位移你总是与整数工作,并因此发生溢出。



Answer 3:

考虑int类型的限制。 它是如何大了一些可以持有?



Answer 4:

int是在大小为32个比特,并且因为它是签名(默认)中,第一比特是用于符号。 当您左移31位,你得到的二进制补 ,这就是- (2 ^ 32)。 当您左移32位,这只是循环所有的方式回到身边1.如果你做到这一点移位与渴望,而不是整数,你会得到你所期望的答案(也就是直到你转移63+位)。



Answer 5:

这里有一个微型基准长的情况下。 在我的笔记本电脑(2.8GHz的),用移而不是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
}


文章来源: Java results differ for (int)Math.pow(2,x) and 1<