zoukankan      html  css  js  c++  java
  • 二进制整数中的“1”

    这里主要通过一些位运算的技巧来找出一个整数的二进制表示中1的个数或其中某些特殊的1的位置。

    1 的个数

    求二进制表示中1的个数存在时间复杂度为O(n)(n为1的个数)的算法。 其要点是 若整数 x 不为0, 表达式(指C语言表达式) x&(x-1) 的运算结果是将 x 的二进制表示中最右侧的1消除后的值, 若x为0, 表达式的值为0。 这样, 若 x 不为0, 我们就可以通过表达式  x = x&(x-1) 反复消除 x 最右侧的1直到x为0, 消除的次数即为所求1的个数。

    C语言代码(输入为32位无符号整型)

    1 int number_of_ones(uint32_t x) {
    2     int result = 0;
    3     while (x) {
    4         x = x & (x - 1);
    5         result++;
    6     }
    7     return result;
    8 }

    最右侧1的位置

    最右侧1的位置通过表达式 x ^ (x & (x-1))计算, 如, x: 0x12345678, x ^ (x & (x-1)) : 0x00000008

    1 uint32_t right_most_one(uint32_t x) {
    2     return x ^ (x & (x - 1));
    3 }

    最左侧1的位置

    求最左侧1的位置相对比较复杂, 下面是一种比较直接的算法。

    1 uint32_t left_most_one(uint32_t x) {
    2     uint32_t test = x & (x - 1);
    3     while (test) {
    4         x = test;
    5         test = x & (x - 1);
    6     }
    7     return x;
    8 }

    在Java ArrayDeque 的 allocateElements 源码中看到一种比较有意思的算法, 它用来计算大于一个数的2的整数次幂。 我们可以对所求2的次幂按位右移一位来求最左侧1的位置。

    下面给出源代码    ps: 自行思考一下算法的原理 :)

     1 uint32_t left_most_one2(uint32_t x) { 
     2     uint32_t tmp = x;
     3     tmp |= (tmp >> 1);
     4     tmp |= (tmp >> 2);
     5     tmp |= (tmp >> 4);
     6     tmp |= (tmp >> 8);
     7     tmp |= (tmp >> 16);
     8     tmp++;
     9     return tmp ? (tmp >> 1) : (0x80000000);
    10 }

    参考

    http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayDeque.java

  • 相关阅读:
    关于Android的布局
    一个新的开端
    Flux的基础概念和实战入门
    在Redux中使用插件createAction之后
    学习
    Object.assign() 对象的扩展
    Redux 中的CombineReducer的函数详解
    React组件的防呆机制(propTypes)
    css的新特性 calc () 使用
    shim和polyfill有什么区别
  • 原文地址:https://www.cnblogs.com/william-cheung/p/4641685.html
Copyright © 2011-2022 走看看