JAVA移位运算与进制转换

关于数据的基础知识

众所周知,在计算机中,数据都是以2进制的方式储存。举个最最最简单的例子

10进制整数 1 以2进制表示 1
10进制整数 2 以2进制表示为10
10进制整数 16 以2进制表示为10000

这样看起来很简单的样子。但是在我们解读2进制数据的时候会有个很大的麻烦。例如:

A把10进制的整数16保存成10000发送给B。如果A不告诉B他使用的是10进制数据的话,那么多于B来说,10000可以为10进制的16,也可以是8进制的20,也可以是16进制的10,B就会懵逼的问A:“你传给我的是什么鬼“。

上面的例子足以说明数据类型对于数据的重要性。

为什么计算机是2进制呢?因为理论是最佳的进制是e进制,即2.718…。正常来说3进制与其更为接近,然而对于制造业来说,2进制更方便生产,所以就变成了2进制。

在java中1个int类型占用多少位呢?我们来做个测试

System.out.println(-1);
// output:11111111111111111111111111111111

A仔细的数了几遍以后确定确实是32位。于是A说:”新技能get!原来int是32位”。
然而A又错了。在java中,int确实固定为32位。不过在其他语言中int并不一定是32位(在C中有仔细说明int类型的问题)。

Java中short是16位-32768~32768这时:

System.out.println((short)32770);
//output: -32766

有符号类型的最高位表示正负(0正,1负),所以对于16位有符号类型的数字最大值应该为Math.pow(2,15)。当数字在Math.pow(2,15)Math.pow(2,16)之间的时候,就会出现最高位被置为1,导致出现负数。(java没有无符号类型)

说了这么多进入正题:
    在JAVA中总共有3种移位运算符。
* >> 有符号右移
* << 右符号左移
* >>> 无符号右移

有符号和无符号的区别在于对最高位的处理。

有符号移位的时候回保留最高位的状态,例:

System.out.println(Integer.toBinaryString(-1));
//output: 11111111111111111111111111111111

System.out.println(Integer.toBinaryString(-1>>1));
//output: 11111111111111111111111111111111

System.out.println(Integer.toBinaryString(-1>>>1));
//output: 01111111111111111111111111111111

因为对于低位的处理无符号和有符号是相同的所以不存在无符号左移

那么这跟进制转换有毛关系?

再举个栗子:

2进制的10000等于16进制的多少呢?

思路1:10000是2的4次方等于16等于16进制的10。(确实毛关系没有!)

不过这是人的思维。

思路2:运用移位运算进行计算:

在2进制中4位代表16进制一位所以10000等于00010000把4位看作1位那么0001等于10000等于0所以16进制为10.

再来看:
在2进制中3位代表8进制中的1位,10000等于010000等于八进制中的2位010000,其中010等于2所以8进制中为20。

A恍然大悟!原来是这么玩的,这时A又问了十分愚蠢的问题:平时都是用10进制,研究这个有啥用?

然而位运算就是2进制的,虽然代码上写的是9 & 2其实这个也是通过对应2进制进行计算的。

A最后问:说了着么多你到底想告诉我什么?

因为这就是Integer中对于进制转换的实现。


 /**
     * Convert the integer to an unsigned number.
     */
    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf, true);
    }


     static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
        int charPos = len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            buf[offset + --charPos] = Integer.digits[val & mask];
            val >>>= shift;
        } while (val != 0 && charPos > 0);

        return charPos;
    }

A吐血身亡!!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值