Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java掩码会用0x1F移位操作数?_Java_Bit Manipulation - Fatal编程技术网

为什么Java掩码会用0x1F移位操作数?

为什么Java掩码会用0x1F移位操作数?,java,bit-manipulation,Java,Bit Manipulation,在Java中: (0xFFFFFFFF << 1) = 0xFFFFFFFE = 0b1111111111111110 : : : (0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000 (0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000 (0xFFFFFFFF <<

在Java中:

(0xFFFFFFFF <<  1) = 0xFFFFFFFE = 0b1111111111111110
                :         :               :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000
当然,这是可以修复的,但是发现这些bug可能非常耗时(我只是花了几个小时跟踪一个类似的bug)。 那么,我的问题是:在移出所有位时,是否有理由不返回逻辑值

更新: 我在C99中尝试了这一点,使用了以下方法:

#include<stdio.h>
main()
{
   int i, val;
   for (i = 0; i <=36; i++) {
       val = (-1 << i);
       printf("%d :\t%d\n", i, val);
   }
}

当然,有:这是大多数处理器(特别是x86)实现位移位的方式,要做您想做的事情——检查移位是否大于32,如果大于32,则返回零——需要一个分支,这在现代CPU上可能很昂贵。这不仅仅是“令人讨厌”,它还可以将事情的发展速度降低几个数量级

简言之,做你想做的事情会给一个操作增加大量的开销,而高性能代码会让这个操作变得非常快速

作为参考,该逻辑与
%
不完全相同,它是一个掩码。详情请参阅:

如果左侧操作数的提升类型为int,则仅将右侧操作数的五个最低阶位用作移位距离。这就好像右侧操作数接受了位逻辑AND运算符(§15.22.1),掩码值为0x1f(0b11111)。因此,实际使用的移动距离始终在0到31之间(包括0到31)

JLS 15.19如果左侧操作数的提升类型为int,则仅将右侧操作数的五个最低阶位用作移位距离。这就好像右侧操作数接受了位逻辑AND运算符(§15.22.1),掩码值为0x1f(0b11111)。因此,实际使用的移动距离始终在0到31之间(包括0到31)


简单地说,
0xFFFFFFFF我一直在使用Java,但从未见过!答案就在这个所谓的问题上,Java规范说,就像你推测的,最低5位。我可以给出一个理由:在x86上实现这样的移位会很烦人,因为本机移位指令也会做掩码的事情。(顺便说一句,它没有做模运算,模运算会有被除数的符号。它屏蔽了所有高位),所以它不是一个bug。这是一个特色。请注意,必须定义它的作用。另一个选项是,如果>=32,则将其定义为0结果。请注意,在C中,将数字超出范围[0 31]的32位整数移位的结果是未定义的。我刚刚查阅了一些移位器的基本逻辑图,这现在是有意义的。在原来的8088和8086以及我相信的80286上,使用可变操作数(CL寄存器)的移位指令将使用CL加载内部寄存器;当该寄存器为非零时,它们将递减寄存器并执行移位。因此,计算
myInt16>>240
将比
myInt16>>15
花费更多的时间,但计算的结果相同[这些都是16位处理器,因此32位值的移位通常通过子程序处理]。请注意,
myInt16>>259
的行为可能类似于
myInt16>>3
,因为CL只有8位。
int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
    ; // code...
#include<stdio.h>
main()
{
   int i, val;
   for (i = 0; i <=36; i++) {
       val = (-1 << i);
       printf("%d :\t%d\n", i, val);
   }
}
warning: left shift count >= width of type