首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

不使用判斷敘述求兩數最大值:位元運算與函式指標表技巧

     編輯:關於C++

核心思路

利用正負號位元(Sign Bit)區分數值大小關係,透過函式指標表跳轉至對應比較邏輯,完全避開 if/else、?:、比較運算子。

關鍵技術細節

  1. 取得符號位:int bits = sizeof(int) * 8 - 1; int sign = x >> bits;(算術右移保留符號位,正數為 0,負數為 -1)。
  2. 正規化旗標:abs(sign) 將 -1 轉為 1,正數仍為 0。
  3. 編碼組合旗標:Flag = s1 * 2 + s2,產生 0~3 四種情況:
    • 0: x≥0, y≥0 (同正)
    • 1: x<0, y≥0 (異號,y較大)
    • 2: x≥0, y<0 (異號,x較大)
    • 3: x<0, y<0 (同負)
  4. 同號比較:z = x - y; s = z >> (bits+32); return t[abs(s)];(利用溢位特性與高位擴展判斷差值符號)。
  5. 異號直接判斷:正數必大於負數,return t[Flag - 1];。

完整實作碼

#include <iostream>
#include <cmath>

#define BITS (sizeof(int) * 8 - 1)

static int CheckFlag(int x, int y) {
    int s1 = abs(x >> BITS);
    int s2 = abs(y >> BITS);
    return s1 * 2 + s2;
}

static int SameSign(int Flag, int x, int y) {
    int t[2] = {x, y};
    long z = (long)x - y;  // 使用 long 避免溢位未定義行為
    int s = abs(z >> (BITS + 32));  // 取得差值符號位
    return t[s];
}

static int DiffSign(int Flag, int x, int y) {
    int t[2] = {x, y};
    return t[Flag - 1];  // Flag=1 回傳 y(正數), Flag=2 回傳 x(正數)
}

static int (*FuncList[4])(int, int, int) = {SameSign, DiffSign, DiffSign, SameSign};

static int Max(int x, int y) {
    int Flag = CheckFlag(x, y);
    return (*FuncList[Flag])(Flag, x, y);
}

int main() {
    int x, y, z;
    std::cout << "請輸入 x (-32768~32767): "; std::cin >> x;
    std::cout << "請輸入 y (-32768~32767): "; std::cin >> y;
    z = Max(x, y);
    std::cout << "最大值: " << z << std::endl;
    return 0;
}

原理分析與現代觀點

  • 教學價值:展示位元操作、函式指標表、避免分支預測失誤的底層技巧。
  • 實務缺陷:依賴算術右移實作定義行為、long 寬度假設、abs(INT_MIN) 未定義行為、可讀性極差。
  • 現代最佳實踐:直接使用 std::max(x, y) 或 (x > y) ? x : y,編譯器會優化為條件移動指令(CMOV),無分支預測罰則。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved