題目:求 max(a, b),**禁止使用** if、?:、switch、循環、比較運算符 (>, < 等)。
對有符號整數 d = a - b:
d >= 0 (a ≥ b) → 最高位 (符號位) 為 0。d < 0 (a < b) → 最高位為 1。將符號位提取為 0/1 索引,查表選擇 a 或 b。
#includeint max_no_branch(int a, int b) { int d = a - b; // 算術右移 31 位 (假設 32 位 int) 提取符號位 // d >= 0 → 0x00000000 (0) // d < 0 → 0xFFFFFFFF (-1) // 轉無符號右移避免實現定義行為,再轉回 int int flag = (int)((unsigned int)d >> 31); // 0 或 -1 // 利用 flag 全 0/全 1 特性進行位選擇 // flag = 0 → 選 a (b & 0 = 0, a & ~0 = a) // flag = -1 → 選 b (b & -1 = b, a & 0 = 0) // 但更簡潔:用數組索引 (flag 轉為 0/1) int idx = (flag == 0) ? 0 : 1; // 這裡用了 ?: 違反題意,改用位運算轉換 // 標準無分支轉換:flag 是 0 或 -1 // (flag & 1) 即為 0 或 1 int arr[2] = {a, b}; return arr[flag & 1]; // flag=0 → 0; flag=-1 (0xFFFFFFFF) & 1 = 1 } // 更優雅的純位運算版 (無數組) int max_bitwise(int a, int b) { int d = a - b; int flag = (int)((unsigned int)d >> 31); // 0 或 -1 // a ^ ((a ^ b) & flag) // flag=0: a ^ 0 = a // flag=-1: a ^ (a ^ b) = b return a ^ ((a ^ b) & flag); } int main() { int a, b; while (scanf("%d %d", &a, &b) == 2) { printf("max = %d\n", max_bitwise(a, b)); } return 0; }
(unsigned)d >> 31 保證邏輯右移 (高位補 0),結果為 0 或 1。轉 int 得 0 或 -1 (0xFFFFFFFF)。a ^ ((a ^ b) & mask)。
mask = 0 → a ^ 0 = a。mask = -1 (全 1) → a ^ (a ^ b) = b。a - b 可能溢出 (如 INT_MAX - (-1))。工程中若輸入範圍未知,需用無符號運算或更複雜的無溢出比較 (如 (a > b) - (a < b) 但用了比較)。int min_bitwise(int a, int b) {
int d = a - b;
int flag = (int)((unsigned int)d >> 31);
return b ^ ((a ^ b) & flag); // 只需交換 a/b 位置
}
| 方法 | 指令數 | 分支預測 | 適用場景 |
|---|---|---|---|
a > b ? a : b | 少 | 可能失敗 | 通用,現代 CPU 分支預測極強 |
| 位運算無分支 | 固定 5-6 條 | 無分支 | SIMD、GPU、嚴格實時系統、避免旁路攻擊 |