zoukankan      html  css  js  c++  java
  • 求与一个数最接近的2的N次幂

    第一种方法

    public class TestClosest2NthPower {
    
      public static void main(String[] args) {
        System.out.println(test(-1));//1
        System.out.println(test(1));//1
        System.out.println(test(-1));//1
        System.out.println(test(10));//16
        System.out.println(test(16));//16
        System.out.println(test(Integer.MAX_VALUE));//2^30
      }
    
      private static int test(int target) {
        //int类型最大值为(2^31)-1,所以目标能取到的最大值为2^30
        int MAXIMUM = 1 << 30;
        if (target >= MAXIMUM) {
          return MAXIMUM;
        }
        int result = 1;
        while (result < target) {
          result *= 2;
        }
        return result;
      }
    
    }
    

    相当于在2的0次幂和2的30次幂中的31个数中找一个最接近的数。

    [2^0,2^1 ... 2^30]
    

    第二种方法

    public class TestClosest2NthPower2 {
    
      public static void main(String[] args) {
        System.out.println(test(-1));//1
        System.out.println(test(1));//1
        System.out.println(test(-1));//1
        System.out.println(test(10));//16
        System.out.println(test(16));//16
        System.out.println(test(Integer.MAX_VALUE));//2^30
      }
    
      private static int test(int target) {
        //int类型最大值为(2^31)-1,所以目标能取到的最大值为2^30
        int MAXIMUM = 1 << 30;
        if (target >= MAXIMUM) {
          return MAXIMUM;
        }
        int temp = target - 1;
        temp |= temp >> 1;
        temp |= temp >> 2;
        temp |= temp >> 4;
        temp |= temp >> 8;
        temp |= temp >> 16;
        return (temp < 0) ? 1 : temp + 1;
      }
    
    }
    

    示例分析

    以129为例(可以更明显看出效果),先减1为128,二进制表示为

    00000000 00000000 00000000 10000000
    

    右移1位

    00000000 00000000 00000000 01000000
    

    两者按位或

    00000000 00000000 00000000 11000000
    

    保证了前两位都为1,以此类推可以保证第一个1及之后的所有位都为1

    00000000 00000000 00000000 11111111
    

    再加一

    00000000 00000000 00000001 00000000
    

    十进制表示为256。

    核心原理

    核心原理就是将一个数减1的二进制表示的第一个1及之后的所有位都置为1,然后加1,这样得到的数就是2的N次幂,相当于最高位的1向左进1位,之后的所有位都置为0。

    为什么要先减1

    为了兼容一个数已经是2的N次幂的情况。以2的4次幂16为例,减1为15,最后操作结果还是16,如果这个数不是2的N次幂,如15,其实减不减1都可以得到正确结果16。

    使用场景

    ForkJoinPool的构造器中初始化workQueues的容量时就使用到了这种方法。

    第三种方法

    public class TestClosest2NthPower3 {
    
      public static void main(String[] args) {
        System.out.println(test(-1));//1
        System.out.println(test(1));//1
        System.out.println(test(-1));//1
        System.out.println(test(10));//16
        System.out.println(test(16));//16
        System.out.println(test(Integer.MAX_VALUE));//2^30
      }
    
      private static int test(int target) {
        //int类型最大值(2^31)-1,所以目标能取到的最大值为2^30
        int MAXIMUM = 1 << 30;
        if (target >= MAXIMUM) {
          return MAXIMUM;
        }
        int n = -1 >>> Integer.numberOfLeadingZeros(target - 1);
        return (n < 0) ? 1 : n + 1;
      }
    
    }
    

    示例分析

    以129为例(可以更明显看出效果),先减1为128,二进制表示为

    00000000 00000000 00000000 10000000
    

    使用Integer的numberOfLeadingZeros()方法求出前导0的个数为24,-1的二进制表示为

    11111111 11111111 11111111 11111111
    

    无符号右移24位

    00000000 00000000 00000000 11111111
    

    再加一

    00000000 00000000 00000001 00000000
    

    十进制表示为256。

    核心原理

    和上一个方法的原理类似,也是将一个数减1的二进制表示的第一个1及之后的所有位都置为1,然后加1。

    使用场景

    这种方法参考的就是HashMap中计算容量大小的算法。

    参考

    求最接近数n的2的次方数

  • 相关阅读:
    Vue.js中学习使用Vuex详解
    vuex存储和本地存储(localstorage、sessionstorage)的区别
    Java 编译与反编译
    Vue导航守卫beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave详解
    Vue生命周期简介和钩子函数
    微信开发----被动回复用户消息
    C#4.0 System.Dynamic
    Mvc5 控制器,视图简单说明
    JQuery 禁用后退按钮
    防止用户多次点击
  • 原文地址:https://www.cnblogs.com/strongmore/p/15475489.html
Copyright © 2011-2022 走看看