右移以执行除以2开-1

我知道我可以使用右移执行除以2。

为简单起见,采用4位数系统

-1 - 1111 -2 - 1110 -3 - 1101 -4 - 1100 -5 - 1011 -6 - 1010 -7 - 1001 -8 - 1000 7 - 0111 6 - 0110 5 - 0101 4 - 0100 3 - 0011 2 - 0010 1 - 0001 0 - 0000 

如果我尝试表演

 6 / 2 = 0110 >> 1 = 0011 = 3 -6/ 2 = 1010 >> 1 = 1101 = -3 

对+ ve和-ve数都有效

但是,当来到1

 1 / 2 = 0001 >> 1 = 0000 = 0 -1/ 2 = 1111 >> 1 = 1111 = -1 

似乎在-1中有一个特殊情况,因为右移然后将其移动到负无穷大。

目前,我需要对此进行特殊检查,因为我期待-1 / 2 = 0。

我想知道你是如何在代码中处理这个exception的? 你这家伙检查了吗?

任何负奇数都不起作用。 但是要回答你的问题,如果你知道你可以有负数,只需除以2.这将变为jit /编译器修复的转变。

@Anon在技术上是正确的。

但是, 最佳做法是使用/运算符进行除法,并将微优化保留给JIT编译器。 JIT编译器能够通过常量优化除法作为移位/添加序列… 当这是执行平台的最佳选择时

做这种事情(可能)是一种过早的优化,如果您的代码需要在多个Java平台上快速运行,那么它可能是一种反优化。

有一天我感到无聊,并且对于2个人的力量进行了分析。 以为我会在这里发布任何感兴趣的人。

在Windows上的HotSpot VM 1.6上,使用j /= 4跨-100000000到100000000在大约12秒内运行时使用j = (j >= 0) ? j >> 2 : ~(~j+1 >> 2) + 1; j = (j >= 0) ? j >> 2 : ~(~j+1 >> 2) + 1; 跑了2.5秒。

Linux上的OpenJDK VM 1.6分为5.5秒,轮class为1.5秒。

这表明JIT编译器并没有真正做任何对2分区的权力感兴趣的事情。

海湾合作委员会设法优化了部门,使其比翻转和轮class更快。

~(~j+1 >> 2) + 1使用二进制补码来翻转正数,移位并将其翻转。

 long j = 0; for (long i = -100000000; i < 100000000; i++) { j = i; j /= 4; } System.out.println(j);` 

VS

 long j = 0; for (long i = -100000000; i < 100000000; i++) { j = i; j = (j >= 0) ? j >> 2 : ~(~j+1 >> 2) + 1; } System.out.println(j);` 

如果你向右移动除以2,你总是向下“向四舍五入” – 如果为正则朝向零,如果为负则向远离它。

如果这不是你想要的,你可以纠正它:

 if (n & 1 > 0 && n < 0) result += 1; 

我不想这么说,但我在代码中没有处理这个问题,因为我不使用位移来进行乘法或除法。 这让我想起了过早的优化 。

为什么你认为你需要进行位移除而不是更可读的x / 2

在奇数情况下,两个操作都会导致结果中的楼层操作。

  • 3/2 – > floor(1.5)=> 1
  • -3/2 – > floor(-1.5)=> -2

你可以把支票,像\

 if ( isOdd(number) && isNegative(number) ) result++;