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

C語言避免溢出求兩數平均值:三種安全方法對比

     編輯:關於C語言

C語言避免溢出求兩數平均值:三種安全方法對比

直接計算 (a + b) / 2 若 a+b 溢出會導致錯誤。本文介紹三種無溢出算法,適用於有符號/無符號整數、浮點數。

方法一:差值法(推薦,通用)

int avg_diff(int a, int b) {
    return a + (b - a) / 2;  // 等價於 (a+b)/2 但無溢出風險
}

原理:a + (b-a)/2 = (2a + b - a)/2 = (a+b)/2。b-a 不會溢出(同符號時差值絕對值較小)。

方法二:位運算法(無符號整數專用)

unsigned int avg_bit(unsigned int a, unsigned int b) {
    return (a & b) + ((a ^ b) >> 1);
}

原理:a+b = (a&b)<<1 + (a^b),平均值右移 1 位。(a&b) 為進位,(a^b) 為不進位和。

方法三:浮點數轉換法(簡單但有精度考量)

double avg_double(double a, double b) {
    return (a + b) / 2.0;  // 雙精度範圍極大,實際無溢出風險
}

原文代碼分析與修正

原代碼:

c = (a - b) / 2.0;
if (c <= 0) sum = b + c;
else sum = c + b;

等價於 b + (a-b)/2 = (a+b)/2,邏輯正確但分支多餘。簡化為 a + (b-a)/2 更清晰。

完整測試程序

#include <stdio.h>
#include <limits.h>

int avg_safe(int a, int b) {
    return a + (b - a) / 2;
}

int main() {
    // 測試極值
    printf("INT_MAX=2147483647, INT_MIN=-2147483648\n");
    printf("avg(INT_MAX, INT_MAX) = %d\n", avg_safe(INT_MAX, INT_MAX));  // 2147483647
    printf("avg(INT_MIN, INT_MIN) = %d\n", avg_safe(INT_MIN, INT_MIN));  // -2147483648
    printf("avg(INT_MAX, INT_MIN) = %d\n", avg_safe(INT_MAX, INT_MIN));  // -1
    printf("avg(100, 200) = %d\n", avg_safe(100, 200));  // 150
    return 0;
}

對比總結

方法適用類型優點缺點
差值法所有整數、浮點數通用、簡潔、無分支需注意除法截斷方向
位運算法無符號整數無除法、硬件友好有符號數需調整
浮點轉換浮點數、小整數直觀大整數精度損失
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved