Interpretation of toUnsignedString method
I saw that there is a method in Integer that converts int into a Unsigned type string, but there are several points that are not very clear. After querying the information, I understand it as follows:
/** * Convert the integer to an unsigned number. */ private static String toUnsignedString(int i, int shift) { char[] buf = new char[32]; int charPos = 32; int radix = 1 << shift; int mask = radix - 1; do { buf[-charPos] = digits[i & mask]; i >>>= shift; } while (i != 0); return new String(buf, charPos, (32 - charPos)); }The parameter shift here represents the binary system. If it is binary, shift is 2, octal is 8, and the corresponding mask is calculated as 1 and 7. Continuously extract the corresponding characters in the digits array through mask and i.
In this way, i performs a logical right-shift operation every time, and the highest bit adds zero, so that after continuous logical right-shift, i will become 0
In addition, adopting do-while is to prevent the buf array from getting its value when i itself is 0.
Interpretation of toString method
// This array represents the ten-digit part of the number, and this array will be used below. final static char [] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', } ;// This array represents the single-digit part of a number, and this array will be used below. If each part of the array is combined, two-digit integers can be obtained in all cases within 100. final static char [] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', } ; public static String toString(int i) { if (i == Integer.MIN_VALUE) // Add 1 here. At first, I don't know what it means. Later, if I find that a negative number is found, I need to add a negative sign in front of it, so the size of the string must be added 1.// The part passed in stringSize here is positive, in the array below // Map int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); return new String(0, size, buf); } static void getChars(int i, int index, char[] buf) { int q, r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } // For integers over 65536, first perform the following processing, // In this process, in units of 100, that is, the remainder is controlled in two digits// This just maps to the above ten-digit and single-digit array, and writes two digits in the buf array at once. This is undoubtedly much faster than finding each digit while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; buf [--charPos] = DigitOnes[r]; buf [--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); // For integers less than or equal to 65536, the following part can be directly performed // And this place is divided by 10, but the implementation is not directly divided // instead, find a 52429/2^19 is about 0.1000... // It is equivalent to dividing i by 10, but what I don't know is why it is not directly// Divided by 10, maybe because the accuracy is insufficient, division produces a floating point number, // Maybe it will be inaccurate, and then multiply the divisor by 10 to get the number of more than 10 digits// part. By i-the number with more than ten digits in this part, you get the number of single digits for (;;) { q = (i * 52429) >>> (16+3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... buf [--charPos] = digits [r]; i = q; if (i == 0) break; } if (sign != 0) { buf [--charPos] = sign; } } final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 999999, 999999, 9999999, 9999999, Integer.MAX_VALUE }; // This should be optimized here, and the bits of integer data are stored through sizeTable //, from one to 10 bits: 2147483647, // This processing method is cleverly static int stringSize(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) return i+1; }Interpretation of the highestOneBit method
public static int highestOneBit(int i) { // HD, Figure 3-1 i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1); }This method is very interesting. I calculated it myself before I understood its essence. The function of this method is to find the value of the integer represented by the largest bit of an integer. This function is realized here through displacement. Let’s give a simple example. For 128, binary is 1000 0000. Let’s take him as an example:
Move 1 digit
1000 0000
0100 0000
|-------------
Move 2 digits
1100 0000
0011 0000
|------------
Move 4 bits
1111 0000
0000 1111
|------------
Move 8 bits
1111 1111
0000 0000
|------------
Mobile 16 bits
1111 1111
0000 0000
|------------
1111 1111
The final result is as you can see. All the following bits are filled with 1, and all the following bits are subtracted to get the integer represented by the highest bit.
bitCount method analysis
public static int bitCount(int i) { // HD, Figure 5-2 i = i - ((i >>> 1) & 0x55555555); i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f; i = i + (i >>> 8); i = i + (i >>> 16); return i & 0x3f; } This method was really useless for a long time to study, and later I figured out a rough idea:
In the first line, the implementation is to group the binary bits of the integer type into two and two, and then count the number of 1 among the two bits. I don’t know how this formula comes from, but it is indeed the case.
The second line implements the grouping of four and four binary bits of the integer, and then calculates the shift addition within the segment, which is 1001-> 10 + 01 = 11. It is equivalent to three 1s. The third line is to group eight binary bits of the integer, and then add displacements similar to the above method. Of course, this is achieved through some specific shifts and operations.
Next are sixteen groups and thirty-two groups, and finally merge the statistics into the statistics represented by the last few digits.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.