• Java位运算和相关应用&剑指offer不用加减乘除做加法


    1. Java中的移位运算

    有两个符号移动——

      符号左移:<<

      符号右移:>>

    这字面理解就是,带符号位的移动咯,左移很容易理解,空出来的低位补0就好,效果相当于乘以2

    主要要区分的是——符号右移>>   和    无符号右移>>>

    符号右移——

      保留符号位,然后右边数值位空出来的用符号的那个  值  来补

    无符号右移——不管左侧最高位是1还是0,左侧补上的空位统统用0填充

      比如10111110 10001010  10000000 00000000,他是多少我们就不理了

      

      我们右移29位,也就是101后面的都被移掉了;

      如果是无符号右移>>>:00000000 00000000 00000000 00000101——结果是5

      如果是符号右移>>:11111111 11111111 11111111 11111101——结果是-3

    这里顺便复习下,Java中的负数用的是补码——

    正数的补码 = 原码

    负数的补码 = {原码符号位不变} + {数值位按位取反后+1}    or = {原码符号位不变} + {数值位从右边数第一个1及其右边的0保持不变,左边安位取反}

    所以这个数字相当于是10000000 00000000 00000000 00000011=-3

    所以一共——符号左移,符号右移还有个无符号右移,符号左移直接补0没毛病,符号右移保留符号位,空出来的数值位用符号位的值来补,无符号右移直接补0;

    2. 剑指offer的不用加减乘除法做加法

     
    一看就是要用到位运算,但不好意思不会哦哈哈哈
    要知道几个东西:
        1. 两个数直接进行异或操作,相当于不考虑进位的加法,类比到十进制就是99+99=88;为啥呢?你想啊,二进制无非是0和1,那只有0和1相加是直接得1嘛,刚好就异或咯
        2. 两个数进行与操作,是每个位相加后产生的进位,类比到十进制就是99+99=11,就9+9=18嘛,进位为1,所以应该左移然后加上上面那个1
    得到的不考虑 进位的结果就对了
        3. 进位+不考虑进位的结果  在十进制中,就是结果了,比如99+99 = 88+110 = 198,但二进制这里不是直接用异或就可以解决了,因为这个过程可能还有用进位
    如:101+111,正确应该是=1100,不考虑进位的相加结果(异或)=010;  进位结果(与操作左移一个)=1010,你会发现1010+0010还有个进位,所以这里不能直接用异或解决,还要用一次上面的两步。
    所以还是要用1,2步来做,直到进位为0
     
     
    上下代码吧:
    public class Solution {
        public int Add(int num1,int num2) {
            int push, sum;
            do {
                sum = num1 ^ num2;//不考虑进位的加法
                push = (num1 & num2) << 1;//每个位产生的进位,左移一个位才是应该进行加法的位置
                num1 = sum;
                num2 = push;
            } while(push != 0);
            
            return push ^ sum;
        }
    }

    3. 移位操作的简单应用 

    ①判断整数a是奇数还是偶数

      a&1 = 0 偶数

      a&1 = 1 奇数

    这个原理也很容易理解嘛,在二进制中,除了第一位是1,其他都是偶数吧,8,4,2啥的,所以要是奇数,一定要第一位为1吧

    ②不用temp交换两个整数

    先要直到一个原理——一个整数a在异或另一个整数b两次以后所得的值还是整数a。就6^2^2 =6,这个通过异或的特点也不难理解吧。

    然后,要做到交换,只要分别进行

     a = a ^ b;  
    
     b = a ^ b; // b=a^b^b=a
    
     a = a ^ b; // a=a^b^a^b^b=a^b^a=b
  • 相关阅读:
    ElasticSearch工作原理
    prometheus监控es集群
    es索引调优
    ES中Refresh和Flush的区别
    网络服务器技术Apache与Nginx,IIS的不同
    shell里/dev/fd与/proc/self/fd的区别
    常用抓包工具
    Ubuntu Kubuntu Xubuntu Lubuntu Dubuntu Mythbuntu UbuntuBudgie区别
    Android的Looper.loop()消息循环机制
    申请读写sd卡权限shell
  • 原文地址:https://www.cnblogs.com/wangshen31/p/12304171.html
Copyright © 2020-2023  润新知