「請手寫 Integer.toBinaryString(int i) 的核心邏輯,不允許調用現成 API」
// JDK 1.8 源碼 java.lang.Integer
public static String toBinaryString(int i) {
return toUnsignedString(i, 1); // shift=1 表示二進制
}
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32]; // int 32 位,最多 32 個字符
int charPos = 32; // 從尾部向前填充
int radix = 1 << shift; // 基數:二進制=2,八進制=8,十六進制=16
int mask = radix - 1; // 掩碼:二進制=1(0b1),八進制=7(0b111)...
do {
buf[--charPos] = digits[i & mask]; // 取最低位映射字符
i >>>= shift; // 無符號右移
} while (i != 0);
return new String(buf, charPos, 32 - charPos);
}
// 字符映射表:0-9, a-z
final static char[] digits = {
'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f','g','h','i','j',
'k','l','m','n','o','p','q','r','s','t',
'u','v','w','x','y','z'
};
以 i = 13 (0b1101) 為例,shift=1 (二進制): 初始:buf[32], charPos=32, mask=1, radix=2 第1輪:i=13 (1101) i & mask = 1 → buf[31] = '1' i >>>= 1 → i=6 (0110) charPos=31 第2輪:i=6 (0110) i & mask = 0 → buf[30] = '0' i >>>= 1 → i=3 (0011) charPos=30 第3輪:i=3 (0011) i & mask = 1 → buf[29] = '1' i >>>= 1 → i=1 (0001) charPos=29 第4輪:i=1 (0001) i & mask = 1 → buf[28] = '1' i >>>= 1 → i=0 charPos=28 循環結束,返回 new String(buf, 28, 4) → "1101"
public static String toBinaryStringManual(int num) {
if (num == 0) return "0";
char[] buf = new char[32];
int pos = 32;
while (num != 0) {
buf[--pos] = (num & 1) == 1 ? '1' : '0';
num >>>= 1;
}
return new String(buf, pos, 32 - pos);
}
public static String toBaseString(int num, int base) {
// base 必須是 2 的冪次:2, 4, 8, 16, 32...
char[] buf = new char[32];
int pos = 32;
int shift = 31 - Integer.numberOfLeadingZeros(base); // log2(base)
int mask = base - 1;
do {
int digit = num & mask;
buf[--pos] = Character.forDigit(digit, base);
num >>>= shift;
} while (num != 0);
return new String(buf, pos, 32 - pos);
}
toBinaryString 展示了 JDK 開發者對 位運算、無符號移位、字符映射、緩衝區複用 的極致優化。面試手寫時,抓住 mask 提取低位 + >>> 右移 + 逆向填充 buf 三步曲,即可寫出正確、高效的實現。理解其通用化設計(shift/mask 參數化),更能舉一反三應對八進制、十六進制轉換題目。