右移以执行除以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++;