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;
        }
  • 相关阅读:
    姐姐的vue(1)
    LeetCode 64. Minimum Path Sum 20170515
    LeetCode 56. 56. Merge Intervals 20170508
    LeetCode 26. Remove Duplicates from Sorted Array
    LeetCode 24. Swap Nodes in Pairs 20170424
    LeetCode 19. Remove Nth Node From End of List 20170417
    LeetCode No.9 Palindrome Number 20170410
    LeetCode No.8. String to Integer (atoi) 2017/4/10(补上一周)
    LeetCode No.7 Reverse Integer 2017/3/27
    LeetCode No.4 Median of Two Sorted Arrays 20170319
  • 原文地址:https://www.cnblogs.com/henuzyy/p/12722320.html
Copyright © 2011-2022 走看看