Java Integer.highestOneBit(i)代码

转载 2013年12月05日 17:21:48
、在写代码的过程中,偶尔使用到了
  1. Integer.highestOneBit(i)  
这个函数调用。使用的第一感觉就是这个函数是干什么用的,通过查看文档得知,这个函数的作用是取 i 这个数的二进制形式最左边的最高一位且高位后面全部补零,最后返回int型的结果。

首先来补充一点背景知识。

1、在计算机系统中,数值一律使用补码来表示和存储。主要原因是使用补码可以将符号位和其它位统一处理;同时,减法也可按照加法来处理。另 外,   两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
- 补码与原码的转换过程几乎相同。
    - 数值的补码表示(分两种)
        - 正数的补码:与原码相同
        - 负数的补码:符号位位1,其余位位该数绝对值的原码按位取反;然后整个数加1
    - 已知一个数的补码,求原码的操作分为两种情况
        - 如果补码的符号位“0”,表示是一个正数,所以补码就是该数的原码
        - 如果补码的符号位为“1”,表示是一个负数,求原码的操作可以是:符号位位1,其余各位取反,然后整个数加1。
2、移位运算符就是在二进制的基础上对数字进行平移。Java按照平移的方向和填充数字的规则分为三种:<<左移,>>带符号右移 和>>>无符号右移。
3、 在Java的移位运算中,byte、short和char类型移位后的结果会变成int类型,对于byte、short、char和int进行移位时,对于char、short、char和int进行移位操作时,规定实际移动的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是移动65次移位1次得到相同的结果。
    (1) <<  运算规则:按二进制形式吧所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
    语法格式:
         需要移位的数字<<移位的次数
         例如:4<<2 ,则是将数字4左移2位
     计算过程
         4<<2
        Java中一个int数占四个字节,那么4的二进制数字为00000000 00000000 00000000 00000100,然后把该数字左移两位。其它的数字都朝右平移两位,最后在低位(右侧)的两个空位补零。则得到的最终结果是00000000 00000000 00000000 00010000,即转换为十进制数16。
         在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方。
         在溢出的前提前,则不符合这个规律。读者可以尝试输出(long)1610612736*4和1610612736<<2这两个结果进行比对。
    (2)>>运算规则:按二进制形式吧所有的数字都向右移动对应的位置,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。
     语法格式:
         需要移位的数字>>移位的次数
         例如:-4>>2和4>>2,则是将数字 -4和4右移2位
     计算过程
         4>>2
         Java中一个int数占四个字节,同样4的二进制为00000000 00000000 00000000 00000100,然后把该数字右移两位。其它的数字都朝左平移两位,最后在高位补符号位(该数是正数,全补零),得到的结果是00000000 00000000 00000000 00000001,即使十进制的1。数学意义就是右移移位相当于除2,右移n位相当于除以2的n次方。
        4>>2
         由于负数在计算机中是以补码的形式存储的,那么-4的二进制为11111111 11111111 11111111 11111100,然后把该数字右移两位,其它数字都朝左平移两位,最后在高位补符号位(该数是负数,全补一),得到的结果是11111111 11111111 11111111 11111111(补码格式),即是十进制的-1。
    (3)>>>运算规则:按二进制形式吧所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。正数运算结果与带符号右移相同,对于负数来说则不同。
         对于4>>>2和-4>>>2运算,可以通过上述例子进行类推。

了解了Java的位运算之后,来看下  Integer.highestOneBit (i) 这个函数的实现代码:
  1. publicstaticinthighestOneBit(int i) {  
  2.      // HD, Figure 3-1  
  3.      i |= (i >>  1);  
  4.      i |= (i >>  2);  
  5.      i |= (i >>  4);  
  6.      i |= (i >>  8);  
  7.      i |= (i >> 16);  
  8.      return i - (i >>> 1);  
  9.  }  

1、第一步的作用是把最高位1右移移位,并与原数据按位取或。那么这就使得最高位和它的下一位是连续两个1。
2、第二步的作用是把刚刚移位得到连续两个1继续右移两位并与原数据按位取或。那么这就使得最高两位和它的下两个连续位组成四个连续的1。
3、 以此类推,最终得到的i是从开始的最高位到结束全是1。并减去i不带符号的右移一位,即可得到一个int数据的最高位的值。
4、上述情况是针对于i不为零和负数的情况,如果i为零,那么得到的结果始终为零。如果i位负数,那么得到的结果始终是-2147483648。即等于Integer.MIN_VALUE。(原因在于负数的最高位始终为1,即是负数的符号位)
 
此函数的最重要理解点在与要始终把握二进制的最高位进行运算处理,那么对于函数中的右移一位、两位、四位、八和十六位就好理解了。同理,对于long类型的取最高位运算应该需要加一条语句 i|=(i>>32); 原因在于long类型在Java中是64位的。
Long类型的hightestOneBit(i)代码如下:
  1. public static long highestOneBit(long i) {  
  2.     // HD, Figure 3-1  
  3.     i |= (i >>  1);  
  4.     i |= (i >>  2);  
  5.     i |= (i >>  4);  
  6.     i |= (i >>  8);  
  7.     i |= (i >> 16);  
  8.     i |= (i >> 32);  
  9.     return i - (i >>> 1);  
  10. }  

java i++和++i的区别

//i++和++i是有区别的, //i++和++i都代表着i=i+1; //i++是在一个先使用原值,然后加1,即先使用i的值,后让i+1. //++i则是先加1后使用,即先让i+1后再使用i的新值....
  • q2267671366
  • q2267671366
  • 2014年12月23日 14:36
  • 2608

浅谈java之++i和i++区别

浅谈java之++i和i++区别                   今天简单谈谈关于java的一个误区,相信很多刚开始学习java的朋友都会遇到这个问题,虽然问题很简单,但是经常容易搞混,说说jav...
  • u011747761
  • u011747761
  • 2015年01月09日 16:31
  • 10314

深入理解JavaI/O流

其实我个人觉得,javaI/O流是一种比较乏味的事情。因为看不到明显的运行效果,但是输入输出程序都需要用到I/O操作即:允许程序读取外部数据、用户输入数据,使用输出机制允许程序记录运行状态,将数据仅处...
  • blueZhangFun
  • blueZhangFun
  • 2015年07月27日 11:59
  • 1384

Java中i++和++i的区别

说来惭愧,从事开发工作也有一年时间了,然而在今天的一个业务逻辑里突然发现原来我对i++和++i都没有理解,或者说我之前的理解是错误的。这对于一个有追求的程序猿是不能容忍的。知道之后,迅速恶补学习,现在...
  • qq_34471736
  • qq_34471736
  • 2017年01月18日 11:41
  • 3320

《JAVA I/O最详解》

刚开始学Java时候,一直搞不懂Java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂。而且没有结合到java7 的最新技术,所以自己结合API来整理一下,有错的话请指正,...
  • self_realian
  • self_realian
  • 2016年07月19日 17:31
  • 1785

java中的i++ 和 ++i 以及 for循环

今天在看java的i++  和++i 的区别,感觉自己还是会绕。正好整理下。 i++:先赋值,后计算; ++i;先计算,后赋值。 看下面代码:public class Text { public s...
  • allenjay11
  • allenjay11
  • 2016年04月14日 21:14
  • 2584

Md5加密中为什么要 & 0xff

《Md5加密中为什么要 & 0xff》 这里首先要搞明白一个代理(自己设想的):  *   byte有8位,假如全部都是 11111111 那么对应的int(10进制)类型就是 255  *   虽然...
  • u013008795
  • u013008795
  • 2017年03月19日 12:13
  • 203

深入理解 java I/O

Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道。在当今这个数据大爆炸...
  • Mr_Tim
  • Mr_Tim
  • 2016年04月06日 11:42
  • 840

Java I/O 模型的演进

什么是同步?什么是异步?阻塞和非阻塞又有什么区别?本文先从 Unix 的 I/O 模型讲起,介绍了5种常见的 I/O 模型。而后再引出 Java 的 I/O 模型的演进过程,并用实例说明如何选择合适的...
  • kkkloveyou
  • kkkloveyou
  • 2016年03月01日 21:17
  • 1447

Java I/O 流详解

原文地址: http://blog.csdn.net/jiangwei0910410003/article/details/22376895 摘要: Java 流在处理上分为字符流和...
  • jason_rainbow
  • jason_rainbow
  • 2016年03月17日 11:40
  • 405
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java Integer.highestOneBit(i)代码
举报原因:
原因补充:

(最多只允许输入30个字)