java源码位运算(java中位数算法)
本文目录一览:
JAVA位运算怎么用的???
Java 位运算 Java 位运算[转]一java源码位运算,Java 位运算1.表示方法: 在Java语言中,二进制数使用补码表示,最高位为符号位,正数java源码位运算的符号位为0,负数为1。补码的表示需要满足如下要求。 (l)正数的最高位为0,其余各位代表数值本身(二进制数)。 (2)对于负数,通过对该数绝对值的补码按位取反,再对整个数加1。2.位运算符 位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算。位运算符可以分为逻辑运算符(包括~、&、|和^)及移位运算符(包括、)。1)左移位运算符()则将运算符左边的运算对象向右移动运算符右侧指定的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0java源码位运算;若值为负,则在高位插入1。3)Java也添加了一种“无符号”右移位运算符(),它使用了“零扩展”:无论正负,都在高位插入0。这一运算符是C或C++没有的。
关于JAVA的位运算
~是取反运算
首先,你要知道java中的int是32位的
其次,正数以原码的形式存储,负数以补码的形式存储
4的二进制是0000 0000 0000 0000 0000 0000 0000 0100
取反后得1111 1111 1111 1111 1111 1111 1111 1011
java中都是有符号数,首位是1,所以是负数,负数也就是补码,也就是说
1111 1111 1111 1111 1111 1111 1111 1011是补码
补码,反码加1后得源码
转换成源码得0000 0000 0000 0000 0000 0000 0000 0101
这个数是5,加上符号就是-5
请教java位运算问题?
Java 位运算 Java 位运算[转]一,Java 位运算1.表示方法: 在Java语言中,二进制数使用补码表示,最高位为符号位,正数的符号位为0,负数为1。补码的表示需要满足如下要求。 (l)正数的最高位为0,其余各位代表数值本身(二进制数)。 (2)对于负数,通过对该数绝对值的补码按位取反,再对整个数加1。2.位运算符 位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算。位运算符可以分为逻辑运算符(包括~、&、|和^)及移位运算符(包括、)。1)左移位运算符()则将运算符左边的运算对象向右移动运算符右侧指定的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1。3)Java也添加了一种“无符号”右移位运算符(),它使用了“零扩展”:无论正负,都在高位插入0。这一运算符是C或C++没有的。
java中的位运算符及其用法。
位逻辑运算符有“与”(AND)、“或”(OR)、“异或(XOR)”、“非(NOT)”,分别用“”、“|”、“^”、“~”表示。
下面的例子说明了位逻辑运算符:
// Demonstrate the bitwise logical operators.
class BitLogic {
public static void main(String args[]) {
String binary[] = {
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
};
int a = 3; // 0 + 2 + 1 or 0011 in binary
int b = 6; // 4 + 2 + 0 or 0110 in binary
int c = a | b;
int d = a b;
int e = a ^ b;
int f = (~a b) | (a ~b);
int g = ~a 0x0f;
System.out.println(" a = " + binary[a]);
System.out.println(" b = " + binary[b]);
System.out.println(" a|b = " + binary[c]);
System.out.println(" ab = " + binary[d]);
System.out.println(" a^b = " + binary[e]);
System.out.println("~ab|a~b = " + binary[f]);
System.out.println(" ~a = " + binary[g]);
}
}
在本例中,变量a与b对应位的组合代表了二进制数所有的 4 种组合模式:0-0,0-1,1-0,和1-1。“|”运算符和“”运算符分别对变量a与b各个对应位的运算得到了变量c和变量d的值。对变量e和f的赋值说明了“^”运算符的功能。字符串数组binary代表了0到15对应的二进制的值。在本例中,数组各元素的排列顺序显示了变量对应值的二进制代码。数组之所以这样构造是因为变量的值n对应的二进制代码可以被正确的存储在数组对应元素binary[n]中。例如变量a的值为3,则它的二进制代码对应地存储在数组元素binary[3]中。~a的值与数字0x0f (对应二进制为0000 1111)进行按位与运算的目的是减小~a的值,保证变量g的结果小于16。因此该程序的运行结果可以用数组binary对应的元素来表示。该程序的输出如下:
a = 0011
b = 0110
a|b = 0111
ab = 0010
a^b = 0101
~ab|a~b = 0101
~a = 1100
左移运算符
左移运算符使指定值的所有位都左移规定的次数。它的通用格式如下所示:
value num
这里,num指定要移位值value移动的位数。也就是,左移运算符使指定值的所有位都左移num位。每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。这意味着当左移的运算数是int类型时,每移动1位它的第31位就要被移出并且丢弃;当左移的运算数是long类型时,每移动1位它的第63位就要被移出并且丢弃。
在对byte和short类型的值进行移位运算时,你必须小心。因为你知道Java在对表达式求值时,将自动把这些类型扩大为 int型,而且,表达式的值也是int型 。对byte和short类型的值进行移位运算的结果是int型,而且如果左移不超过31位,原来对应各位的值也不会丢弃。但是,如果你对一个负的byte或者short类型的值进行移位运算,它被扩大为int型后,它的符号也被扩展。这样,整数值结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单办法是将结果转换为byte型。下面的程序说明了这一点:
// Left shifting a byte value.
class ByteShift {
public static void main(String args[]) {
byte a = 64, b;
int i;
i = a 2;
b = (byte) (a 2);
System.out.println("Original value of a: " + a);
System.out.println("i and b: " + i + " " + b);
}
}
该程序产生的输出下所示:
Original value of a: 64
i and b: 256 0
因变量a在赋值表达式中,故被扩大为int型,64(0100 0000)被左移两次生成值256(10000 0000)被赋给变量i。然而,经过左移后,变量b中惟一的1被移出,低位全部成了0,因此b的值也变成了0。
既然每次左移都可以使原来的操作数翻倍,程序员们经常使用这个办法来进行快速的2的乘法。但是你要小心,如果你将1移进高阶位(31或63位),那么该值将变为负值。下面的程序说明了这一点:
// Left shifting as a quick way to multiply by 2.
class MultByTwo {
public static void main(String args[]) {
int i;
int num = 0xFFFFFFE;
for(i=0; i4; i++) {
num = num 1;
System.out.println(num);
}
}
}
该程序的输出如下所示:
536870908
1073741816
2147483632
-32
初值经过仔细选择,以便在左移 4 位后,它会产生-32。正如你看到的,当1被移进31位时,数字被解释为负值。
右移运算符
右移运算符使指定值的所有位都右移规定的次数。它的通用格式如下所示:
value num
这里,num指定要移位值value移动的位数。也就是,右移运算符使指定值的所有位都右移num位。
下面的程序片段将值32右移2次,将结果8赋给变量a:
int a = 32;
a = a 2; // a now contains 8
当值中的某些位被“移出”时,这些位的值将丢弃。例如,下面的程序片段将35右移2次,它的2个低位被移出丢弃,也将结果8赋给变量a:
int a = 35;
a = a 2; // a still contains 8
用二进制表示该过程可以更清楚地看到程序的运行过程:
00100011 35
2
00001000 8
将值每右移一次,就相当于将该值除以2并且舍弃了余数。你可以利用这个特点将一个整数进行快速的2的除法。当然,你一定要确保你不会将该数原有的任何一位移出。
右移时,被移走的最高位(最左边的位)由原来最高位的数字补充。例如,如果要移走的值为负数,每一次右移都在左边补1,如果要移走的值为正数,每一次右移都在左边补0,这叫做符号位扩展(保留符号位)(sign extension),在进行右移操作时用来保持负数的符号。例如,–8 1 是–4,用二进制表示如下:
11111000 –8
1
11111100 –4
一个要注意的有趣问题是,由于符号位扩展(保留符号位)每次都会在高位补1,因此-1右移的结果总是–1。有时你不希望在右移时保留符号。例如,下面的例子将一个byte型的值转换为用十六进制表示。注意右移后的值与0x0f进行按位与运算,这样可以舍弃任何的符号位扩展,以便得到的值可以作为定义数组的下标,从而得到对应数组元素代表的十六进制字符。
// Masking sign extension.
class HexByte {
static public void main(String args[]) {
char hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f''
};
byte b = (byte) 0xf1;
System.out.println("b = 0x" + hex[(b 4) 0x0f] + hex[b 0x0f]);
}
}
该程序的输出如下:
b = 0xf1
无符号右移
正如上面刚刚看到的,每一次右移,运算符总是自动地用它的先前最高位的内容补它的最高位。这样做保留了原值的符号。但有时这并不是我们想要的。例如,如果你进行移位操作的运算数不是数字值,你就不希望进行符号位扩展(保留符号位)。当你处理像素值或图形时,这种情况是相当普遍的。在这种情况下,不管运算数的初值是什么,你希望移位后总是在高位(最左边)补0。这就是人们所说的无符号移动(unsigned shift)。这时你可以使用Java的无符号右移运算符,它总是在左边补0。下面的程序段说明了无符号右移运算符。在本例中,变量a被赋值为-1,用二进制表示就是32位全是1。这个值然后被无符号右移24位,当然它忽略了符号位扩展,在它的左边总是补0。这样得到的值255被赋给变量a。
int a = -1;
a = a 24;
下面用二进制形式进一步说明该操作:
11111111 11111111 11111111 11111111 int型- 1的二进制代码
24 无符号右移24位
00000000 00000000 00000000 11111111 int型255的二进制代码由于无符号右移运算符只是对32位和64位的值有意义,所以它并不像你想象的那样有用。因为你要记住,在表达式中过小的值总是被自动扩大为int型。这意味着符号位扩展和移动总是发生在32位而不是8位或16位。这样,对第7位以0开始的byte型的值进行无符号移动是不可能的,因为在实际移动运算时,是对扩大后的32位值进行操作。下面的例子说明了这一点:
// Unsigned shifting a byte value.
class ByteUShift {
static public void main(String args[]) {
char hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
byte b = (byte) 0xf1;
byte c = (byte) (b 4);
byte d = (byte) (b 4);
byte e = (byte) ((b 0xff) 4);
System.out.println(" b = 0x"
+ hex[(b 4) 0x0f] + hex[b 0x0f]);
System.out.println(" b 4 = 0x"
+ hex[(c 4) 0x0f] + hex[c 0x0f]);
System.out.println(" b 4 = 0x"
+ hex[(d 4) 0x0f] + hex[d 0x0f]);
System.out.println("( b 0xff) 4 = 0x"
+ hex[(e 4) 0x0f] + hex[e 0x0f]);
}
}
该程序的输出显示了无符号右移运算符对byte型值处理时,实际上不是对byte型值直接操作,而是将其扩大到int型后再处理。在本例中变量b被赋为任意的负byte型值。对变量b右移4位后转换为byte型,将得到的值赋给变量c,因为有符号位扩展,所以该值为0xff。对变量b进行无符号右移4位操作后转换为byte型,将得到的值赋给变量d,你可能期望该值是0x0f,但实际上它是0xff,因为在移动之前变量b就被扩展为int型,已经有符号扩展位。最后一个表达式将变量b的值通过按位与运算将其变为8位,然后右移4位,然后将得到的值赋给变量e,这次得到了预想的结果0x0f。由于对变量d(它的值已经是0xff)进行按位与运算后的符号位的状态已经明了,所以注意,对变量d再没有进行无符号右移运算。
B = 0xf1
b 4 = 0xff
b 4 = 0xff
(b 0xff) 4 = 0x0f
位运算符赋值
所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式。例如,下面两个语句都是将变量a右移4位后赋给a:
a = a 4;
a = 4;
同样,下面两个语句都是将表达式a OR b运算后的结果赋给a:
a = a | b;
a |= b;
下面的程序定义了几个int型变量,然后运用位赋值简写的形式将运算后的值赋给相应的变量:
class OpBitEquals {
public static void main(String args[]) {
int a = 1;
int b = 2;
int c = 3;
a |= 4;
b = 1;
c = 1;
a ^= c;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
}
}
该程序的输出如下所示:
a = 3
b = 1
c = 6