请用移位的方式打印出一个十进制整数的十六进制形式。提示:按每4个二进制位对整数进行移位和去高位处理,得到的结果就是十六进制数的一位,然后按下面三种方式之一(作为作业,要求每种方式都用到)计算出一个十六进制数值对应的十六进制形式
定义一个数组,其中包含0-F这些字符,然后用要计算的数值作为数组的索引号,即可获得其对应的十六进制数据。 public class Test4 {/** Creates a new instance of Test1 */
public Test4() {
}
public void printMe(){
System.out.println("Hello world");
}
public static void main(String[] args) {
System.out.println(getHexString(23));
}
public static String getHexString(int number){
char[] hex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
StringBuffer sb=new StringBuffer("0x");
int mask=0xF;
for(int i=7;i>=0;i--){
int temp=number>>(i*4);
temp=temp&mask;
sb.append(hex[temp]);
}
return sb.toString();
}
}
那位大哥能给我讲讲那个temp&mask是干嘛的,为啥要这样啊?
还有sb.append(hex【temp】)这一步是干嘛的?谁能给我讲懂啊,我实在是看不懂,请高手给我指教指教啊,我都想了一天了也弄不懂啊,拜托了啊
temp=temp&mask;
sb.append(hex[temp]);第一句表示获得十进制数number向右移动4*i位后的结果,这句话你明白吧?
也就是通过循环逐次获取int型数的32位(每次取出4位)mask=0xF表示一个4位的数1111 (十六进制F表示二进制1111)
第二句话地意思是temp的低四位。
因为上面一行 number>>(i*4) 将获得一个32位的整形temp
而我们只需要其中的低4位,所以采用与操作,将自动将高于低四位的部分置0 (自动补充mask的位置为0,与操作的话计算得到0,这步与操作的实际意义就是获得temp的低4位)第三句,将temp表示的4位二进制数转换成十六进制(从数组中读取字符),这个能明白吧然后将它添加到字符串中(sb最开始初始化为0x也即十六进制字符串的开头,用来表示十六进制)LZ还有什么不明白的吗?
还有就是hex[temp]不明白
5 & 6, 2进制下5是0101,6是0110,0101 & 0110 = 0100
所以 5 & 6 = 4temp & mask
mask = 0XF, 2进制下是 00000000 00000000 00000000 00001111
这样任何一个整数跟mask进行与操作,都会只剩下最后4位
所以temp & mask 得到的结果跟 temp%16 是一样的当temp成为 一个0到15的数以后,用它作为hex数组的下标,hex[temp]中的字符就刚好是0~15在16进制下的表示。
把它们拼接起来,用sb.append()拼接起来,就可以得到最后结果了。
它的二进制表示是:
0000 0000 0000 0000 0000 0000 0001 0111循环在 i 为1 和 0 的时候有实际作用 (其他时,temp为0 这里不做探究)i==1时, temp = number >> 4 = 0000 0000 0000 0000 0000 0000 0000 0001
这里取低四位和不取没有什么区别i==0时, temp = number >> 0 = 0000 0000 0000 0000 0000 0000 0001 0111
注意,此时如果不取低四位则不符合代码本意
所以必须取低四位不知道这样说LZ理解了没有 = =
10 在 16进制下的表示为 A
以此类推
可以看出,任何int跟这个0xF进行&运算,只有二进制的最后4位(也就是低)有效,二进制的高28位计算结果都会变成0,所以也就相当于保留int的低4位,去除int的高28位sb.append(hex[temp])就是把数组hex的下标为temp(这个是计算得到的一个数)的数组元素添加到sb这个字符串缓存对象里。这个帖子几年前好像就有人问了
http://topic.csdn.net/u/20080328/11/8e9a992d-96d3-4edd-89ff-764b584a915c.html不过现在就帖子的链接打不开。
十六进制数表示
0 -> 0
1 -> 1
2 -> 2
3 -> 3
4 -> 4
5 -> 5
6 -> 6
7 -> 7
8 -> 8
9 -> 9
10 -> A
11 -> B
12 -> C
13 -> D
14 -> E
15 -> F比如 1F = 1 * 16 + 15 = 31,这个LZ明白吧?计算机为了区分各各进制数的差别,人为的在数之前加了符号以区别
如16进制前加0x,8进制前加0,这只是为了区分进制 OK?你的程序的输出结果是一个8位的16进制数
为什么是8位?
首先,一个int类型整数为32位二进制,而每4位二进制数可以转换为1位16进制数
为什么?想想 4位二进制数可以表示的数的范围
从 0000 到 1111 也即 0 到 15 也即 十六进制下的 0 到 F! OK?于是,你的程序的思路就是,将number的32位每4位切割,将4位二进制数转成16进制,然后将8位拼接起来,输出字符串这个时候你应该已经注意到 hex字符数组的作用
对于任意的i (i >= 0, i <= 15) 十进制数i的十六进制表示为 hex[i]
比如 当i=10, 十进制数10的十六进制表示为 A 也就是 hex[10]
这样你明白hex字符数组的用处了吧?循环中
temp = number >> (i * 4);
通过循环变量i,逐次取出number的4位二进制数,保存到temp中
比如,令number= 0101 0000 0111 1010 0011 1001 0001 1111
那么 当i=7, temp = number >> 28 将number向右移位28位
对于右移操作,最高位补0(这里不讨论负数、逻辑等问题,有兴趣自己网上搜吧)
于是,temp = number >> 28 = 0000 0000 0000 0000 0000 0000 0000 0101
看,temp的低4位正是 number的 0 到 3 位 0101.
依次循环正好可以取遍number的每4位 LZ 这里明白了吗 码字好累 = =再说 int mask = 0xF
首先,mask为int型,故它为32位二进制数
而0xF为一个十六进制数(0x部分的解释上面已经说了)
0xF = 15 = 1111(二进制)
所以 mask的完整表示为 0000 0000 0000 0000 0000 0000 0000 1111
OK?循环的第二步 temp = temp & mask
注意 与操作中,每一位上,只要有0 则与操作的结果为0 OK?
于是无论temp的值是多少, 前28位的结果都是0 OK?
而 与1之后,结果为原来的值( 0 & 1 = 0, 1 & 1 = 1)
所以 这一步的语义就是:保留temp的低四位! OK?你可能要问,为什么只要低4位?
因为我们说过,每一次循环只处理number的4位
如果不与mask,会有什么结果?
令number= 0101 0000 0111 1010 0011 1001 0001 1111
temp = number >> 24 = 0000 0000 0000 0000 0000 0000 0101 0000
不与mask,则 temp的值为 temp = 1 * 64 + 1 * 16 = 80!
这不仅不符合我们程序的目的,更重要的是,hex数组的下标允许最大值为15,传80进去将会抛出数组下标超界的异常! OK?sb.append(hex[temp]);
首先LZ明白 hex[temp]的意思了吧?
就是根据取出的4位二进制数temp的值(0 到 15),得到其16进制表示(0 到 F)
sb.append(char) 表示,将char加入到字符串的末尾于是循环结束之后,就完成了将number每4位转为16进制并添加到字符串中,返回它的16进制表示呼 = = 累。PS:关于为什么10进制数可以这样转成16进制
首先,计算机中存储数都是存它的2进制表示的
也即一个整形 t = 7 ,实际它是以 0111形式存的
而由于正好 4位2进制数可以转成16进制,所以这就给我们转换16进制形成了便利!