右移以执行除以2开-1

Che*_*eng 7 java algorithm

我知道我可以使用右移执行除以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
Run Code Online (Sandbox Code Playgroud)

如果我尝试表演

6 / 2 = 0110 >> 1 = 0011 = 3
-6/ 2 = 1010 >> 1 = 1101 = -3
Run Code Online (Sandbox Code Playgroud)

对+ ve和-ve数都有效

但是,当来到1

1 / 2 = 0001 >> 1 = 0000 = 0
-1/ 2 = 1111 >> 1 = 1111 = -1
Run Code Online (Sandbox Code Playgroud)

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

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

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

erg*_*sys 18

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

  • +1注意到,如果你想除以2,你可能只是尝试除法运算符,看看它有多好. (2认同)
  • +1 - 还要感谢强调子优化通常不会超过编译器所做的工作,而"天真"选项通常对这样的基本内容有效且正确. (2认同)

Ste*_*n C 12

@Anon在技术上是正确的.

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

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


nik*_*daz 5

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

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

Linux上的OpenJDK VM 1.6分为5.5秒,轮班为1.5秒.

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

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

~(~j+1 >> 2) + 1 使用二进制补码来翻转正数,移位和翻转它.

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

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);`
Run Code Online (Sandbox Code Playgroud)