java中java位运算实现加法问题

Java位运算总结:位运算用途广泛 - 博客频道 - CSDN.NET
LinBilin_的专栏
分类:java 位运算
前天几天研究了下JDK的Collection接口,本来准备接着研究Map接口,可是一查看HashMap类傻眼咯,到处是位运算实现,所以我觉得还是有必要先补补位运算知识,不然代码看起来有点费力。今天系统研究了下,现记录如下。
&&&&&& 首先要明白一个概念,Java位运算是针对于整型类型的二进制进行的移位操作。主要包括位与、位或、位非,有符号左移、有符号右移,无符号右移等等。需要注意一点的是,不存在无符号左移&&&运算符。根据位运算的概念规定,我们首先需要弄明白两个问题,有哪些数据类型是整型数据类型和各数字进制之间转换问题。Java整型数据类型有:byte、char、short、int、long。要把它们转换成二进制的原码形式,必须明白他们各占几个字节。我们都知道,一个字节占8位。
&&&&& 数据类型&&&&&&&&&&&&&&&&&&&&&&&&&& 所占位数
&&&&& byte&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 8&
&&&&& boolean&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&8
&&&&& short&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 16
&&&&& int&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 32&
&&&&& long&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 64&
&&&&& float&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&32&
&&&&& double&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 64&
&&&&& char&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 16
还需要明白一点的是:计算机表示数字正负不是用+ -加减号来表示,而是用最高位数字来表示,0表示正,1表示负
所以比如-4用二进制原码表示就是11 11
下面根据实例一个一个的来说明各种位运算的运算规则:
位与&(真真为真 真假为假 假假为假)
位或|(真真为真 真假为真 假假为假)
位非~(取反码)【注:Java中正数的最高位为0,负数最高位为1,即最高位决定正负符号】
:先取反码,再补码
位异或^(真真为假 真假为真 假假为假)
有符号右移&&(若正数,高位补0,负数,高位补1)
11 11 && 原码
11 11 && 右移,最左边空出两位按规则负数空位补1
00 00 && 解码
00 00 && 补码(补码即最后一位+1)
有符号左移&&(若正数,高位补0,负数,高位补1)
11 11 && 原码
11 11 && 左移,最右边空出两位补0
00 00 && 补码
无符号右移&&&(不论正负,高位均补0)
11 11 && 原码
11 11 && 右移(由于高位均补0,故&&&后的结果一定是正数)
由于数据类型所占字节是有限的,而位移的大小却可以任意大小,所以可能存在位移后超过了该数据类型的表示范围,于是有了这样的规定:
如果为int数据类型,且位移位数大于32位,则首先把位移位数对32取模,不然位移超过总位数没意义的。所以4&&32与4&&0是等价的。
如果为long类型,且位移位数大于64位,则首先把位移位数对64取模,若没超过64位则不用对位数取模。
如果为byte、char、short,则会首先将他们扩充到32位,然后的规则就按照int类型来处理。
学到这里,我想你也可能会问,位运算到底有什么用途或者有哪些场景可以到它。因为位运算的运算效率比直接对数字进行加减乘除高很多,所以当出现以下情景且对运算效率要求较高时,可以考虑使用位运算。不过实际工作中,很少用到它,我也不知道为什么很少有人用它,我想应该是它比较晦涩难懂,如果用它来进行一些运算,估计编写的代码的可读性会不强,毕竟我们写的代码不仅仅留给自己一个人看。
1.& 判断int型变量a是奇数还是偶数&&&&
&&&& a&1& = 0 偶数&
&&&&&a&1 =& 1 奇数&
2.& 求平均值,比如有两个int类型变量x、y,首先要求x+y的和,再除以2,但是有可能x+y的结果会超过int的最大表示范围,所以位运算就派上用场啦。
&&&&& (x&y)+((x^y)&&1);&
3.& 对于一个大于0的整数,判断它是不是2的几次方
&&& ((x&(x-1))==0)&&(x!=0);&
4.&&比如有两个int类型变量x、y,要求两者数字交换,位运算的实现方法:性能绝对高效
5. 求绝对值
&&& int abs( int x )&
&&&& y = x && 31 ;&
&&& return (x^y)-&&&&&&& //or: (x+y)^y&
6.&&取模运算,采用位运算实现:
&&&& a % (2^n) 等价于 a & (2^n - 1)&
7.& 乘法运算&& 采用位运算实现
&&&& a * (2^n) 等价于 a&&& n
8.&&&除法运算转化成位运算
&&&&&&a / (2^n) 等价于 a&& n&
9.&& 求相反数
&&&&& (~x+1)&
10& a % 2 等价于 a & 1&
当然还有牛人使用位运算来实现权限控制,技术,里面的奥秘深不可测
排名:千里之外
(2)(2)(1)(6)(1)(1)(0)(3)(1)(1)(3)(1)(1)(6)(4)(2)(1)(1)(1)(3)(1)(1)(1)(1)(1)(0)(1)(1)(6)(1)(1)(0)(0)(1)(1)(0)(0)(0)(1)(1)(8)(1)(1)(1)(1)(1)(1)(1)(1)(3)(1)(1)(1)(2)(1)(0)(1)(1)(1)(6)(0)(1)(1)(0)(1)(1)(0)(1)(1)(3)(0)一,Java 位运算&
1.表示方法:
在Java语言中,二进制数使用补码表示,最高位为符号位,正数的符号位为0,负数为1。补码的表示需要满足如下要求。
(1)正数的最高位为0,其余各位代表数值本身(二进制数)。
(2)对于负数,通过对该数绝对值的补码按位取反,再对整个数加1。&
2.位运算符
位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算。位运算符可以分为逻辑运算符(包括~、&、|和^)及移位运算符(包括&&、&&和&&&)。&
1)左移位运算符(&&)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)。&
2)&有符号&右移位运算符(&&)则将运算符左边的运算对象向右移动运算符右侧指定的位数。
&有符号&右移位运算符使用了&符号扩展&:若值为正,则在高位插入0;若值为负,则在高位插入1。
3)Java也添加了一种&无符号&右移位运算符(&&&),它使用了&零扩展&:无论正负,都在高位插入0。这一运算符是C或C++没有的。&
4)若对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。
只有右侧的5个低位才会用到。这样可防止我们在一个int数里移动不切实际的位数。
若对一个long值进行处理,最后得到的结果也是long。此时只会用到右侧的6个低位,防止移动超过long值里现成的位数。
但在进行&无符号&右移位时,也可能遇到一个问题。若对byte或short值进行右移位运算,得到的可能不是正确的结果(Java 1.0和Java 1.1特别突出)。
它们会自动转换成int类型,并进行右移位。但&零扩展&不会发生,所以在那些情况下会得到-1的结果。&
在进行位运算时,需要注意以下几点。
(1)&&&和&&的区别是:在执行运算时,&&&运算符的操作数高位补0,而&&运算符的操作数高位移入原来高位的值。
(2)右移一位相当于除以2,左移一位(在不溢出的情况下)相当于乘以2;移位运算速度高于乘除运算。
(3)若进行位逻辑运算的两个操作数的数据长度不相同,则返回值应该是数据长度较长的数据类型。
(4)按位异或可以不使用临时变量完成两个值的交换,也可以使某个整型数的特定位的值翻转。
(5)按位与运算可以用来屏蔽特定的位,也可以用来取某个数型数中某些特定的位。
(6)按位或运算可以用来对某个整型数的特定位的值置l。
3.位运算符的优先级
~的优先级最高,其次是&&、&&和&&&,再次是&,然后是^,优先级最低的是|。&
二, 按位异或运算符^&
&参与运算的两个值,如果两个相应位相同,则结果为0,否则为1。即:0^0=0, 1^0=1, 0^1=1, 1^1=0&
   0^0=0,0^1=1 0异或任何数=任何数&
   1^0=1,1^1=0 1异或任何数-任何数取反&
   任何数异或自己=把自己置0
(1)按位异或可以用来使某些特定的位翻转,如对数的第2位和第3位翻转,可以将数与进行按位异或运算。
                    11 // ^ 0x06 =
(2)通过按位异或运算,可以实现两个值的交换,而不必使用临时变量。
例如交换两个整数a,b的值,可通过下列语句实现:
&a=a^b;   //a=&
&b=b^a;   //b=
&a=a^b;   //a=
(3)异或运算符的特点是:数a两次异或同一个数b(a=a^b^b)仍然为原值a.
&三,Java 中除了二进制的表示方法:&
由于数据在计算机中的表示,最终以二进制的形式存在,所以有时候使用二进制,可以更直观地解决问题。&
&但,二进制数太长了。比如int
类型占用4个字节,32位。比如100,用int类型的二进制数表达将是:&
&面对这么长的数进行思考或操作,没有人会喜欢。因此,C,C++,以及java中
没有提供在代码直接写二进制数的方法。&
&八进制数的表达方法&
&如何表达一个八进制数呢?如果这个数是
876,我们可以断定它不是八进制数,因为八进制数中不可能出7以上的阿拉伯数字。但如果这个数是123、是567,或,那么它是八进制数还是10进制数,都有可能。
&所以规定,一个数如果要指明它采用八进制,必须在它前面加上一个0,如:123是十进制,但0123则表示采用八进制。这就是八进制数的表达方法。
现在,对于同样一个数,比如是100,我们在代码中可以用平常的10进制表达,例如在变量初始化时:&
&我们也可以这样写:
//0144是八进制的100;一个10进制数如何转成8进制。&
&千万记住,用八进制表达时,你不能少了最前的那个0。否则计算机会通通当成10进制。不过,有一个地方使用八进制数时,却不能使用加0,那就是我们前面学的用于表达字符的&转义符&表达法。
&十六进制数的表达方法&
&如果不使用特殊的书写形式,16进制数也会和10进制相混。随便一个数:9876,就看不出它是16进制或10进制。&
&16进制数必须以
0x开头。比如
0x1表示一个16进制数。而1则表示一个十进制。另外如:0xff,0xFF,0X102A,等等。其中的x也也不区分大小写。(注意:0x中的0是数字0,而不是字母O)&
&以下是一些用法示例:
&最后一点很重要,10进制数有正负之分,比如12表示正12,而-12表示负 12,;但8进制和16进制只能用来表达无符号的正整数,如果你在代码中里:-078,或者写:-0xF2,编译器并不把它当成一个负数。
阅读(...) 评论() &string、byte、位运算碰到问题 - Free - ITeye技术网站
博客分类:
情景:java对byte[]做^实现加密,C对Char[]做^运算来解密。
加密,java中对原文转换成byte数组,然后做^运算,这个过程中将返回结果做了一次new String(),得到加密结果。
解密,getBytes()拿到密文,然后做^运算,打印发现结果不是原文了。
原因,new String()会抛弃编码中不存在的byte,处理latin1编码兼容所有的。故去掉中间new String()的步骤就可以了。
* @param str
* @param srclen
public static byte[] cbt_crypt(String str, int srclen) {
String tmp = "badboy_blue";
byte[] key = tmp.getBytes();
byte[] stri = str.getBytes();
for (i=0;i&i++){
stri[i]^=key[j];
j=(j+1)%8;
* @param str
* @param srclen
* @param pos
public static byte[] cbt_crypt(byte[] str, int srclen, int pos)
int j=pos%8;
String tmp = "badboy_blue";
byte[] key = tmp.getBytes();
for (i=0;i&i++) {
str[i]^=key[j];
j=(j+1)%8;
另外附个byte[]和String之间转换信息丢失的问题:
http://blog.csdn.net/xiongyucai/archive//2472662.aspx
badboy_blue
浏览: 29848 次
来自: 深圳
我正不知道怎么配置呢
试试先
我也是习惯了eclipse,又是 ...
cenziboy 写道为什么要用 Eclipse
为什么要用 Eclipse
VC 2010 不行吗?java移位运算的一些基本概念问题,求解释?书上讲的移位运算的“符号位”是不是就是最左边第一位数比如-1 的二进制表示是:, 那符号位就是最左边的1,
1 的二进制表示是:, 那符号位就是最右边的0?还有:左移“>1;" 与
"val=val>>>1;” 出来的结果是一样的?无符号右移">>>" 不是也称为“补0的右移运算”吗?即右移了之后最左边的位数总是0,这是怎么回事?希望理解我的问题之后再回答万分感谢
誓言送粉519
1、移位运算的“符号位”是最左边第一位数(高位);2、左移“>1;"
结果仍是-1,因为右移后高位补“1”,和原来是一样的。被移走的高位1,又被补回来了。
"val=val>>>1;”
结果是,因为高位变成0了。
java int 类型占32位,4字节java中有3中移位运算符:>>,>逻辑右移,运算规则:低位溢出,高位补0“val=val>>1;" 与
"val=val>>>1;” 出来的结果是不一样的,分别为-1和,即11 :右移1位还是 111...
首先 第一个问题-1的二进制表示并不是而是 ,最高位是(最左边的一位)符号位,最高位为0表示是正数,1表示是负数第二个问题算术右移
不改变符号往右移 >>>逻辑右移 并不能保证不改变符号 至于结果我试了一下并不相等。
为您推荐:
扫描下载二维码

我要回帖

更多关于 java的位运算 的文章

 

随机推荐