Java 无符号右移运算符“的用途是什么?”&燃气轮机&燃气轮机&燃气轮机&引用;在爪哇?
我理解Java中无符号右移位运算符“>>>”的功能,但为什么我们需要它,为什么我们不需要相应的无符号左移位运算符?基本上这与符号(数字移位)或无符号移位(通常与像素相关的内容)有关Java 无符号右移运算符“的用途是什么?”&燃气轮机&燃气轮机&燃气轮机&引用;在爪哇?,java,programming-languages,bit-manipulation,Java,Programming Languages,Bit Manipulation,我理解Java中无符号右移位运算符“>>>”的功能,但为什么我们需要它,为什么我们不需要相应的无符号左移位运算符?基本上这与符号(数字移位)或无符号移位(通常与像素相关的内容)有关 由于左移位不处理符号位,因此也是一样(使用>运算符可以将int和long视为32位和64位无符号整数类型,Java语言中缺少这些类型 当您移动不表示数值的内容时,这非常有用。例如,您可以使用32位ints来表示黑白位图图像,其中每个int对屏幕上的32个像素进行编码。如果您需要向右滚动图像,您更喜欢ints左侧的位变
由于左移位不处理符号位,因此也是一样(使用
>
运算符可以将int
和long
视为32位和64位无符号整数类型,Java语言中缺少这些类型
当您移动不表示数值的内容时,这非常有用。例如,您可以使用32位int
s来表示黑白位图图像,其中每个int
对屏幕上的32个像素进行编码。如果您需要向右滚动图像,您更喜欢int
s左侧的位变为零,以便您可以轻松地将相邻int
s的位放入:
int shiftBy = 3;
int[] imageRow = ...
int shiftCarry = 0;
// The last shiftBy bits are set to 1, the remaining ones are zero
int mask = (1 << shiftBy)-1;
for (int i = 0 ; i != imageRow.length ; i++) {
// Cut out the shiftBits bits on the right
int nextCarry = imageRow & mask;
// Do the shift, and move in the carry into the freed upper bits
imageRow[i] = (imageRow[i] >>> shiftBy) | (carry << (32-shiftBy));
// Prepare the carry for the next iteration of the loop
carry = nextCarry;
}
int-shiftBy=3;
int[]imageRow=。。。
int shiftCarry=0;
//最后一个移位位设置为1,其余为0
int mask=(1>>移位)|(进位>>
运算符生成它们
没有相应的
负数的正常右移>
将使其保持为负数。即,符号位将保留
无符号的右移位>
也将移位符号位,并将其替换为零位
不需要有等效的左移位,因为只有一个符号位,它是最左边的位,所以它只在右移位时发生干扰
本质上,区别在于一个保留符号位,另一个移位为零以替换符号位
对于正数,它们的作用相同
有关同时使用>
和>
的示例,请参阅。如果一个人有一个表示数字的int
,并且希望将其除以二的幂,向负无穷大舍入,则有符号右移运算符非常有用。这在进行缩放坐标等显示操作时非常有用;不仅如此比除法快,但在缩放前因比例因子不同而不同的坐标在缩放后将相差一个像素。如果不使用移位,则使用除法,则不起作用。例如,当按两个因子进行缩放时,-1和+1相差两个,因此应在缩放后相差一个,但-1/2=0和1/2=0。如果相反,使用符号如果右移,结果会很好:-1>>1=-1和1>>1=0,正确地产生相隔一个像素的值
无符号运算符在以下情况下很有用:输入预期正好有一个位集,并且希望结果也有一个位集,或者使用循环输出字中的所有位,并希望它干净地终止。例如:
void processBitsLsbFirst(int n, BitProcessor whatever)
{
while(n != 0)
{
whatever.processBit(n & 1);
n >>>= 1;
}
}
如果代码使用有符号右移运算并传递负值,它将无限期地输出1。但是,使用无符号右移运算符,最高有效位的解释结果与其他任何位一样
无符号右移运算符在以下情况下也很有用:从算术上讲,计算将产生一个介于0和4294967295之间的正数,并且希望将该数字除以二的幂。例如,当计算已知为正数的两个int
值之和时,可以使用(n1+n2)>>>1
无需将操作数提升为长
。此外,如果希望在不使用浮点数学的情况下将正的int
值除以类似pi的值,则可以计算((value*5468522205L)>>34)
[(1L
也是找到两个四舍五入平均值的安全有效方法(大)整数:
int mid = (low + high) >>> 1;
如果整数high
和low
接近最大的机器整数,则上述结果是正确的,但
int mid = (low + high) / 2;
由于溢出,可能会得到错误的结果
下面是一个简单的例子,修复了简单二进制搜索中的一个bug。在Java域中,大多数典型的应用程序避免溢出的方法是使用强制转换或大整数,如前面示例中的int-to-long
int hiint = 2147483647;
System.out.println("mean hiint+hiint/2 = " + ( (((long)hiint+(long)hiint)))/2);
System.out.println("mean hiint*2/2 = " + ( (((long)hiint*(long)2)))/2);
BigInteger bhiint = BigInteger.valueOf(2147483647);
System.out.println("mean bhiint+bhiint/2 = " + (bhiint.add(bhiint).divide(BigInteger.valueOf(2))));
你所说的“处理”是什么意思?我在代码中一直使用32位无符号值,而且我从不使用>>>运算符。@TylerDurden没有>>
(例如,当你使用>
)最高有效位(也称为“符号位”)32位或64位值的符号将得到特殊处理-它在移位后被复制到新的符号位,因此>
移位后的值的符号保持不变。对于具有符号的语言(例如C/C++或C#)中的无符号类型,这是不同的。在这些语言中,符号位的内容由第一个操作数的类型控制。由于Java中没有无符号类型,因此该语言最终引入了一个特殊的无符号“右移”运算符.对,正如我所说,我知道它是做什么的。为什么?你关心的是什么情况?@TylerDurden-例如,在BigInteger
中,它使用一个整数数组来存储它的数字。要右移,它将使用>
来右移,除了最重要的数字。实际上,没有也不需要索引d、 我是在评论你的措辞,这可能会给新手一个相反的建议:“这是一样的(当你移植的C代码对无符号整数进行右移时,你最好使用>>>,否则会得到错误的结果。找到平均值的好信息。但是”会引发异常“-不会引发异常,但会由于溢出而导致意外结果精彩的解释!Joshua Bloch在”“”“中给出了此用法的一个示例,修复了朴素二进制搜索中的一个错误。的可能重复项。”