zoukankan      html  css  js  c++  java
  • 位运算

    大致分为其中:按位或(I) 按位与( &)    按位异或(^)   按位取反(~)  左移(<<)  右移(>>)   无符号右移(>>>)

     Java中>>和>>>的区别

    >>:带符号右移。正数右移高位补0,负数右移高位补1。

    >>>:无符号右移。无论是正数还是负数,高位通通补0。

     Leetcode 有一题关于位运算 https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/

    按位或(I)

    有1则为1,无1则为0

    • 1 | 0 = 1 
    • 1 | 1 = 1
    • 0 | 0 = 0

    按位与( &) 

     两个数都为1,则为1,否则为0

    • 1 | 0 = 0
    • 1 | 1 = 1
    • 0 | 0 = 0

    按位异或(^)

    相同位不同则为1,相同则为0。

    • 1 | 0 = 1
    • 1 | 1 = 0
    • 0 | 0 = 0

    按位取反(~)

    为单目运算,是针对数字本身进行按位取反,1变0,0变1

    • 1 = 0
    • 0 = 1

    左移(<<)

    是将一个二进制数,全部向左平移X位

    eg: 将0X23(十六进制数)左移两位

     0X23 = 0010 0011  左移两位就是  1000 1100 。(左移之后右边空出来的位置,全部补零,左边移出的部分忽略)

    右移(>>)  

    和上面的左移刚好相反,(规则是向右移动X位,右边移出的部分忽略,左边空出来的位置,全部补零)

    无符号右移(>>>)

     无符号右移,忽略符号位,空位都以0补齐

    机器数(最高位为符号位,0为正,1为负)

    如:5 机器数为   0000 0101;         -5机器数为  1000  0101

    原码:和机器数一样。

    反码

    正数:和原码一样

    负数:除符号位以外,其余位都按位取反。

    补码:

    正数:和原码一样

    负数:除符号位以外,在反码的基础上,加1

     注意:在使用时,机器都是使用补码进行表示的。

    原码:

    正数的原码是

    原码、反码、补码的概念:

    http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

    重要须知:java虚拟机在表示整数的时候(java都是有符号数,没有无符号的概念),使用补码来进行表示;浮点数使用的是IEEE 754 标准(IEEE 二进制浮点数算术标准)字符串都用的是Unicode字符集和UTF-8编码。 

     -------------------------------------下面为自己理解---------------------------------------------------------------------------

    大端(big endian):低地址存放高有效字节

    小端(little endian):低地址存放低有效字节



     

    通用原则:低索引位存储的是低位值,高索引位存储的是高位值??????是否正确

    java采用的大端【低内存地址-->高内存地址,高位字节排列在低内存地址,所以数据在内存地址排列是如下的格式(byte[3],byte[2],byte[1],byte[0]),刚好是数据的大小顺序】

    现在主流的CPU,intel系列的是采用的little endian的格式存放数据。网络编程中,TCP/IP统一采用大端方式传送数据,所以有时我们也会把大端方式称之为网络字节序

    注意:

    int之类的,低字节位数存放的是低位数据,高字节位数存放的是高位数据。

    int a = 12; 

    十六进制表示为: 00 00 00 0C

    二进制表示为: 00000000 00000000 00000000 00001100

    需要四个字节表示int类型,byte[0],byte[1],byte[2],byte[3]

    存放规则:

    byte[0] = 00001100  

    byte[1] = 00000000

    byte[2] = 00000000

    byte[3] = 00000000

    int b = 5123

    十六进制表示为  0x00 00 14 03

    二进制标示为:00000000 00000000 00010100 00000011

    需要四个字节表示int类型,byte[0],byte[1],byte[2],byte[3]

    存放规则:

    byte[0] = 00000011

    byte[1] = 00010100 

    byte[2] = 00000000 

    byte[3] = 00000000 

    移位操作只是为了将目标byte[]移动到最低位,然后强转为byte,并赋值给对应的byte[]

    大端小端只是指这个字节是按照从小到大、还是从大到小这样的顺序排列

     long/int <-->  byte[]

        public static byte[] getBytes(int data) {
            byte[] bytes = new byte[4];
            bytes[0] = (byte) (0XFF & data);
            bytes[1] = (byte) ((0XFF00 & data) >> 8);
            bytes[2] = (byte) ((0XFF0000 & data) >> 16);
            bytes[3] = (byte) ((0XFF000000 & data) >> 24);
            return bytes;
        }
    
        public static int getInt(byte[] bytes) {
            return (0XFF & bytes[0]) | (0XFF00 & (bytes[1] << 8)) | (0XFF0000 & (bytes[2] << 16)) | (0XFF000000 & (bytes[3] << 24));
        }
    
        public static byte[] getBytes(long data) {
            byte[] bytes = new byte[8];
            bytes[0] = (byte) (data & 0xff);
            bytes[1] = (byte) ((data >> 8) & 0xff);
            bytes[2] = (byte) ((data >> 16) & 0xff);
            bytes[3] = (byte) ((data >> 24) & 0xff);
            bytes[4] = (byte) ((data >> 32) & 0xff);
            bytes[5] = (byte) ((data >> 40) & 0xff);
            bytes[6] = (byte) ((data >> 48) & 0xff);
            bytes[7] = (byte) ((data >> 56) & 0xff);
            return bytes;
        }
    
    
        public static long getLong(byte[] bytes) {
            return (0xffL & (long) bytes[0]) | (0xff00L & ((long) bytes[1] << 8)) | (0xff0000L & ((long) bytes[2] << 16)) | (0xff000000L & ((long) bytes[3] << 24))
                    | (0xff00000000L & ((long) bytes[4] << 32)) | (0xff0000000000L & ((long) bytes[5] << 40)) | (0xff000000000000L & ((long) bytes[6] << 48)) | (0xff00000000000000L & ((long) bytes[7] << 56));
        }
    
        public static byte[] getBytes(double data) {
            long l = Double.doubleToLongBits(data);
            return getBytes(l);
        }
    
        public static double getDouble(byte[] data) {
            long l = getLong(data);
            return Double.longBitsToDouble(l);
        }

    下面是Netty源码的写法:

        /**
         * 大端: 低位放高位地址
         * &(与): 1 & 1=1; 1&0 =0   用1可以保证对应位置不变
         * |(或): 0 | 0=0; 0|1=1  用0可以保证对应位置不变
         * >> / << / >>>  左右移动N位
         */
        public static byte[] setInt(int value) {
            byte[] memory = new byte[4];
            memory[0] = (byte) (value >>> 24);
            memory[1] = (byte) (value >>> 16);
            memory[2] = (byte) (value >>> 8);
            memory[3] = (byte) value;
            return memory;
        }
    
    
        public static int getInt(byte[] memory) {
            return (memory[0] & 0xff) << 24 |
                    (memory[1] & 0xff) << 16 |
                    (memory[2] & 0xff) << 8 |
                    memory[3] & 0xff;
        }
  • 相关阅读:
    缓存算法之LRU与LFU
    银行家算法
    死锁,死锁的四个必要条件以及处理策略
    找出无序数组中位数的方法
    HTTP状态码
    进程调度算法
    宽字节wchar_t和窄字节char的相互转换
    胜天半子
    ? 题目 一道超难的奥数题,猜生日. A告诉B他生日的月份,告诉C他生日的日期 B说:“如果我不知道A的生日,那C肯定也不知道." C说:”本来我不知道,现在我知道了.“ B说:”哦,那我也知道了.
    有对夫妇生有一男一女,一天晚上,成员中的一个杀了另一个,剩下2个成员,1个是帮凶1个是目击者
  • 原文地址:https://www.cnblogs.com/henuzyy/p/12722320.html
Copyright © 2011-2022 走看看