zoukankan      html  css  js  c++  java
  • 十进制转二进制(位运算)

    Java内置了API: Integer.toBinaryString();

    先看源码是怎么写的

    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);
    }
    

    核心是两部分

    一计算mag,mag指的是二进制需要占用的位数, eg: 10 => 1010 需要四位。

    另一个就是formatUnsignedInt(); 去转换,等下去具体看。

    public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        if (i == 0)
            return 32;
        int n = 1;
        if (i >>> 16 == 0) { n += 16; i <<= 16; }
        if (i >>> 24 == 0) { n +=  8; i <<=  8; }
        if (i >>> 28 == 0) { n +=  4; i <<=  4; }
        if (i >>> 30 == 0) { n +=  2; i <<=  2; }
        n -= i >>> 31;
        return n;
    }
    

    这个方法里都是左移右移的位运算,左移就是末尾加0 即乘以2,eg: 10 <<= 1 即 10100 等于20。右移是反过来 10 >>= 1 即 101 等于5。

    所以这几个if是在干嘛呢,举个例子理解,以10为例,我们知道它的二进制是四位,不够十六位,所以再过了第一个if之后会变成1010...(16),其他几个类似,你可以在脑子里过一遍。首先我们确定i最大是31位,而规律就是过完这些if,i 要么是32位要么是31位,那么它再右移31位 结果要么是0要么是1。而n就记录了这个过程中实际补了多少位。我只能分析出这个规律,不能想出如何想到的这样的想法来计算。我们的例子10 对应结果 n = 28; mag = 4; 可以脑补下它执行了哪几个if。

     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;
    }
    

    这是第二部分真正去转换的部分,猛一看不懂这些变量radix mask代表什么意思,但是我们通过debug将值带入进去发现mask = 1。然后得到转换值的关键在于digits[val & mask], digits是定义的一个数组存放了[0-9][a-z]。然后 奇数&1 = 1; 偶数 & 1 = 0; 为什么会这样,还是以10为例 1010 & 0001 只比较最后一位即可 因为任何数 & 0都为0,所以 0 & 1 = 0;实际上digits[0] = 0; digits[1] = 1; 我们可以找到这个方法的核心将最后一位 & 1 然后右移移除最后一位。

    我最后再想一下平时的写法

    public static String int2Binary(int n) {
      StringBuilder result = new StringBuilder();
      while (n > 0) {
        if (n % 2 == 0) {
          result.append("0");
        } else {
          result.append("1");
        }
        n = n / 2;
      }
      return result.reverse().toString();
    }
    

    唔 比内置的实现容易懂,当然效率上肯定会差一些。

  • 相关阅读:
    设置EntityFramework中decimal类型数据精度
    关于vue中的nextTick深入理解
    解决使用VS2013创建的MVC项目在VS2015中打开的各种问题
    mysql免安装版的下载与安装
    酷狗缓存文件kgtemp的加密方式
    PowerDesigner反向生成物理数据模型
    VISUAL STUDIO 2012下的OPENCV 2.4.7安装过程
    讲解DLL内容的比较详细的站点
    strcpy_s与strcpy的区别
    【原创】在VS2012中采用C++中调用DLL中的函数(4)
  • 原文地址:https://www.cnblogs.com/ZouHongxue/p/int2Binary.html
Copyright © 2011-2022 走看看