程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 由C++絕對值函數想到的

由C++絕對值函數想到的

編輯:C++入門知識

   這些天恰好要用到一個絕對值的函數。好吧,你會說這個直接用std::abs不就行了嗎?對的,一開始我也是這樣用的。但是如果去求最小的那個int的值的絕對值,就會導致輸出不正確。如:
[cpp]
int min_int = -2147483648; 
cout<<std::abs(min_int)<<endl; 
       得到的結果仍然是-2147483648!恰好我的程序有可能出現這樣的情況。所以需要自己去完成一個。

1、第一個版本:
[cpp]
unsigned int __abs(int value) 

    return (value >= 0) ? value : -value; 

       仍然是std::abs的老路,不可取!

2、第二個版本:
[cpp]
#include <limits> 
 
unsigned int __abs(int value) 

    return (std::numeric_limits<int>::min() == value || value >= 0) ? value : -value; 

       這個版本比較簡潔,可移植性也很高。std::numeric_limits<int>::min()返回當前系統下int值的最小值,能夠自適應int的內存寬度返回准確的值。當value和最小的int值相等或者value不為負數時,我們直接進行位對位的拷貝——因為unsigned int沒有符號位,所以完全可行的。當value為除最小值外的負數時,直接取相反數即可。
       但這個版本需要用到兩次條件判斷,能不能再優化一下呢?所以出現了:

3、第三個版本:
[cpp]
unsigned int __abs(int value) 

    unsigned int copyed_value = value; 
    return (copyed_value > 0x80000000) ? -value : copyed_value; 

        因為32位下最小的int值為0x80000000——最高位符號位為1。當位對位拷貝到unsigned int中時,仍然是這個值。但其他的負數除了最高位為1外,其余位置也有值,比如-1的16進制表示為:0x80000001。所以,我們先執行位對位的拷貝,到copyed_value中。所以出現了判斷情況:
       (1)如果copyed_value是大於0x80000000的,說明value是負數,所以我們直接取相反數(-value);
       (2)如果copyed_value是等於0x80000000的,說明value恰好是最小的那個負數,執行位對位拷貝後,copyed_value中存放的就是value的絕對值,所以返回copyed_value;
       (3)如果copyed_value是小於0x80000000,說明value為正數。直接去alue或者copyed_value即可。
       通過分析,我們將(2)和(3)合並到一起,返回copyed_value。所以,采取第三種方案,就只有一次比較操作。比第二種方案省一次。但是這種方案第一眼看去可能易讀性上不是很好。

       權衡三種方案,應該說各有利弊。三種情況各有適用的地方。如果你的函數不考慮最小int值的絕對值,可以采用std::abs即可;如果需要考慮但不必擔心性能問題,那麼第二種方案是你最好的選擇!但如果你既要考慮最小int值的絕對值問題,又要考慮性能問題,建議采用第三個方案。

       這個問題雖然簡單,但裡面透射出來的東西可真不少。其實我們在編程工作中,從細節出抓起,往往能夠獲得很多收獲。



摘自 Arnozhang的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved