preface

In the daily development of our Java programmers because of object-oriented, in fact, about bit operation or contact less, but in fact, look at the source code of some frameworks, found that there are more clever design through bit operation, today we will have a little understanding of bit operation.

Based on review of

Bit and byte

1) A bit is a measure of the speed of data transmission. Byte is a unit of file size. It is often abbreviated as B.

1 Byte=8 bits. On a computer, an English letter takes up 1 Byte of hard drive space, and a Chinese character takes up 2 bytes. The diagram below:

For example, in our Java language, an int is 4 bytes, which is 32 bits, and I’ll talk about the use of int in some source code later

Number of machines

The binary representation of a number in a computer is called the machine number of that number. Machine numbers are signed. In a computer, the highest bit of a number is used to store the symbol. Positive numbers are 0 and negative numbers are 1.

Source code, inverse code, complement
The original code

Converting a number to binary (the number of machines) is this value

Radix-minus-one complement

The expression of the inverse code is: the inverse of a positive number is itself; The inverse of a negative number is based on its original code, the sign bit is unchanged, the rest of the bits are inverse.

complement

The expression of complement is: the complement of a positive number is itself; The complement of a negative number is based on its original code, with the same sign bits, the other bits reversed, and finally +1. (i.e. +1 on the basis of inverse)

Decimal primitive The original code Radix-minus-one complement complement
10 0000, 1010, 0000, 1010, 0000, 1010,
– 10 1000, 1010, 1111, 0101, 1111, 0110,
5 0000, 0101, 0000, 0101, 0000, 0101,
– 5 1000, 0101, 1111, 1010, 1111, 1011,
Design sense

Simplified the design of the computer, the computer can only add operation, through the design of complement, so that it can be in this design, subtraction operation. For example, 1-1 in the computer is actually 1 + (-1) that is, the complement operation, that is to say, all calculations are the use of the number of complement, after the completion of the calculation and then change back to the source code. The calculation based on negative numbers can be seen in detail later.

Operator (&, |, ^ ~, > >, < <, > > >)

& “with”

Two numbers, from the lowest to the highest, correspond one to one. If both values of a bit are 1, the corresponding bit of the resulting value is 1; otherwise, it is 0.

int x = 1; / / 0000 0001
int y = 2; / / 0000 0010
Copy the code

To facilitate subsequent calculations and comparisons, I use these two numbers for all my subsequent operators

x&y = 0001 & 0010  = 0000 = 0
y&x = 0010 & 0001  = 0000 = 0
x&x = 0001 & 0001  = 0001 = 1
y&y = 0010 & 0010  = 0010 = 1
Copy the code
| “or”

Two numbers, from the lowest to the highest, correspond one to one. If one of the two values of a bit is 1, the corresponding bit of the resulting value is 1; otherwise, it is 0.

x|y = 0001 | 0010  = 0011 = 3
y|x = 0010 | 0001  = 0011 = 3
x|x = 0001 | 0001  = 0001 = 1
y|y = 0010 | 0010  = 0010 = 2
Copy the code
^ xOR

When two operands are xor, the value of the same bit is 0 if the value is the same, and 1 if the value is different.

x^y = 0001 ^ 0010  = 0011 = 3
y^x = 0010 ^ 0001  = 0011 = 3
x^x = 0001 ^ 0001  = 0000 = 0
y^y = 0010 ^ 0010  = 0000 = 0 
Copy the code
~ take the opposite

For this number, each 1 becomes 0, and each 0 becomes 1

~x = ~0000 0001 =  1111 1111. (omitted)1111 1110 
Copy the code
>> “Right shift operator”

Rule A >> B calculates the binary value of value A from bit 0 to bit B-1, and moves b bit to the right as a whole. The sign bit remains the same, and the bit complement value 0 is left empty at the high level.

 y>>1 = 0000..0010.(source) >>1 = 0000..0010.(complement) > >1 = 0000..0001.(complement)=0000.0001= (source)1
-y>>1 = 1000.0010(source) >>1 = 1111.1110(complement) > >1 = 1111.1111.(complement)=1000..0001.(source)= -1
// In fact, all operations have gone through the source-compliance-computation-source process, which is omitted below directly to the conclusion
Copy the code
<< “left shift operator”

Rule A << b calculates the binary value of value A from bit 0 to bit B-1, and moves b bit to the left as a whole. The sign bit remains the same, and the bit complement value left by the low position is 0.

 y<<1 =  0000.0010<<1= 0000.0100 = 4
-y<<1 =  1000.0010<<1= 1000.0100 = -4
Copy the code

Formula summary:

  • a >> b = a / ( 2 ^ b )
  • a << b = a * (2 ^ b)
>>> “Unsigned Right shift”
  • Ignoring the sign bit, the vacancies are filled with zeros

The unsigned right shift rule is the same as the right shift rule, except that the left number is filled with 0 regardless of whether it is negative or positive. The unsigned right shift only evaluates to negative numbers, and the result must be a positive number, because it makes no sense for positive numbers

 y>>>1 =  0000.0010 >>>1 = 0000.0001 = 1
-y>>>1 =  1000.0010(source) > >1 = 1111.1110(Complement) >>1= =0111.1111(the calculated complement) =0111.1111(source code) =2147483647
// Because the highest complement of a negative number 0 becomes a positive number, the positive number's complement source code is itself, so it becomes a large number, this point should be paid special attention to.
Copy the code
The sample application
  • Two numbers interchangeably
x = x^y = 0001 ^ 0010 = 0011 = 3
y = y^x = 0010 ^ 0011 = 0001 = 1
x = x^y = 0011 ^ 0001 = 0010 = 2 
Copy the code

It’s just interchangeable, so I can write it like this:

x^=y,
y^=x,
x^=y
Copy the code

Based on the above features, you can realize the encryption of a number, a string of numbers, an xor operation on an intermediate number, get encrypted data, decryption again xor on the middle number.

  • | with &, an int representing multiple attributes

Have you ever encountered such a scenario when writing code: a class has an attribute represented by Boolean, and after a period of time, a new Boolean needs to be added to represent the new attribute… So it looks like the following code:

public class Human {
    /** * is a student */
    private boolean isStudent;

    /** * is an adult */
    private boolean isAdult;

    /** * Is single */
    private boolean isSingle;

    // private boolean is.....


    public void setStudent(boolean student) {
        isStudent = student;
    }

    public boolean isStudent(a) {
        return isStudent;
    }
    
    // setter and getter...
}
Copy the code

So now, using bits, we can write:

public class Human {
    /** * is a student */
    public static final int IS_STUDENT = 1;

    /** * is an adult */
    public static final int IS_ADULT = 2;

    /** * Is single */
    public static final int IS_SINGLE = 4;

    private int properties;

    public void setProperties(int properties) {
        this.properties = properties;
    }

    public boolean isStudent(a) {
        return(properties & IS_STUDENT) ! =0;
    }

    public boolean isAdult(a) {
        return(properties & IS_ADULT) ! =0;
    }

    public boolean isSingle(a) {
        return(properties & IS_SINGLE) ! =0;
    }

    @Override
    public String toString(a) {
        return "Is it a student?" + isStudent() + "Adult or not." + isAdult() + "Single or not"+ isSingle(); }}Copy the code

We provide a setProperties method is only in the incoming parameters, where the incoming parameters we use “|” operator, separated we want to specify the properties of the below is the test code:

public static void main(String args[]) {
        Human human = new Human();
        human.setProperties(Human.IS_STUDENT);
        System.out.println(human.toString());

        human.setProperties(Human.IS_STUDENT | Human.IS_SINGLE);
        System.out.println(human.toString());

        human.setProperties(Human.IS_SINGLE | Human.IS_ADULT);
        System.out.println(human.toString());

        human.setProperties(Human.IS_STUDENT | Human.IS_SINGLE | Human.IS_ADULT);
        System.out.println(human.toString());
    }
Copy the code

The output

Student or nottrueWhether adultfalseWhether the singlefalseStudent or nottrueWhether adultfalseWhether the singletrueStudent or notfalseWhether adulttrueWhether the singletrueStudent or nottrueWhether adulttrueWhether the singletrue
Copy the code

First of all, notice that the constants I defined are 1, 2, 4 except 0, that is, 2 ^ n

a = 1 =  0000 0001
b = 2 =  0000 0010
c = 4 =  0000 0100
d = 8 =  0000 1000
e = 16 = 0001 0000
f = 32 = 0010 0000
/ /... I can define up to 31 numbers.
Copy the code

Thus, we use “|” operator of any two or more calculated, had, in fact, keep them on their own sites such as:

int x = c|d|e = 0001 1100 = 28
// check whether x contains c or d
 // Use &
 
 int y = z&c = 0000 0100 = 4 = c
 int z = z&d = 0000 1000 = 8Theta is equal to d as long as it doesn't0000 0000That is0If the & operator is true, we can determine whether to include the number, which is the definition of the method of the above function.Copy the code

As we all know, the Android LinearLayout has this attribute “showDividers” :

    <LinearLayout
        android:showDividers="beginning|middle|end"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
Copy the code

How many positions can you show the dividing line in the view? Why do you use this property to represent three positions? Let’s enter the source code to see:

    private int mShowDividers;

    public static final int SHOW_DIVIDER_NONE = 0;

    public static final int SHOW_DIVIDER_BEGINNING =1;
    
    public static final int SHOW_DIVIDER_MIDDLE = 2;
    
    public static final int SHOW_DIVIDER_END = 4;

    public void setShowDividers( int showDividers) {
        if (showDividers == mShowDividers) {
            return; } mShowDividers = showDividers; setWillNotDraw(! isShowingDividers()); requestLayout(); }protected boolean hasDividerBeforeChildAt(int childIndex) {
        if (childIndex == getVirtualChildCount()) {
            return(mShowDividers & SHOW_DIVIDER_END) ! =0;
        }
        boolean allViewsAreGoneBefore = allViewsAreGoneBefore(childIndex);
        if (allViewsAreGoneBefore) {
            return(mShowDividers & SHOW_DIVIDER_BEGINNING) ! =0;
        } else {
            return(mShowDividers & SHOW_DIVIDER_MIDDLE) ! =0; }}Copy the code

I listed above the core of only a few lines of code, first of all, all the display attributes are an int mShowDividers said set method using the specified “|”, looking at the core of the code in the ontouch method drawing line, will call this method, the judgment method is to use the & operator. The View.MeasureSpec and Gravity classes also use bit-operators, which I won’t go into here.

Android:

  • LinearLayout
  • View.MeasureSpec
  • Grivaty