一次 IDA 反匯編經歷中,發現一段極其精簡的指令序列竟只是在計算兩個整數的較小值。當時未細究,事後重新推導,發現其核心思想極具啟發性——分類討論 + 降低元數。
目標:給定整數 x, y,求 m = min(x, y)。
令 z = x - y,則:
x < y,則 z < 0,需 m = x = y + z> y,則 z > 0,需 m = y = y + 0統一為 m = y + g(z),其中一元分段函數 g(z) 滿足:
g(z) = z (z < 0)
g(z) = 0 (z > 0)
利用算術右移的符號擴展特性:
z < 0 → z >> 31 = 0xFFFFFFFF
z > 0 → z >> 31 = 0x00000000
故 g(z) = (z >> 31) & z 完美滿足要求。最終算法:
int min_int(int x, int y)
{
int z = x - y;
return y + ((z >> 31) & z);
}
同理,max(x, y) = x - ((x - y) >> 31 & (x - y))。
>> 31,而非 32。GCC 對 >> 32 會警告 right shift count >= width of type,且行為未定義。x - y 若溢位屬 UB。工程上可改用無符號減法或編譯器內建 __builtin_ssub_overflow 檢查,或直接信任補碼環繞(大多數平台行為一致)。-O2 下已能自動將 x < y ? x : y 優化為條件移動指令(CMOV)或無分支位運算,手寫此算法多為教學或極端優化場景。f(x, y) 轉化為一元函數 g(z),利用中間量 z = x - y 消除對 x 的直接依賴。這兩大思想不僅適用於位運算技巧,更是演算法設計與數學建模的通用方法論。