編程中無窮大常量的設定技巧(轉)

轉自 http://aikilis.tk/程序員

若是問題中各數據的範圍明確,那麼無窮大的設定不是問題,在不明確的狀況下,不少程序員都取0x7fffffff做爲無窮大,由於這是32-bit int的最大值。若是這個無窮大隻用於通常的比較(好比求最小值時min變量的初值),那麼0x7fffffff確實是一個完美的選擇,可是在更多的狀況下,0x7fffffff並非一個好的選擇。算法

  1. 不少時候咱們並不僅是單純拿無窮大來做比較,而是會運算後再作比較,例如在大部分最短路徑算法中都會使用的鬆弛操做:
    if (d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v];
    咱們知道若是u,v之間沒有邊,那麼w[u][v]=INF,若是咱們的INF取0x7fffffff,那麼d[u]+w[u][v]會溢出而變成負數,咱們的鬆弛操做便出錯了,更通常的說,0x7fffffff不能知足「無窮大加一個有窮的數依然是無窮大」,它變成了一個很小的負數。
  2. 除了要知足加上一個常數依然是無窮大以外,咱們的常量還應該知足「無窮大加無窮大依然是無窮大」,至少兩個無窮大相加不該該出現災難性的錯誤,這一點上0x7fffffff依然不能知足咱們。

因此咱們須要一個更好的傢伙來頂替0x7fffffff,最嚴謹的辦法固然是對無窮大進行特別處理而不是找一個很大很大的常量來代替它(或者說模擬它),可是這樣會讓咱們的編程過程變得很麻煩。在我讀過的代碼中,最精巧的無窮大常量取值是0x3f3f3f3f,我不知道是誰最早開始使用這個精妙的常量來作無窮大,不過個人確是從一位不認識的ACMer(ID:Staginner)的博客上學到的,他/她的不少代碼中都使用了這個常量,因而我本身也嘗試了一下,發現很是好用,而當我對這個常量作更深刻的分析時,就發現它真的是很是精巧了。編程

  1. 0x3f3f3f3f的十進制是1061109567,也就是10^9級別的(和0x7fffffff一個數量級),而通常場合下的數據都是小於10^9的,因此它能夠做爲無窮大使用而不致出現數據大於無窮大的情形。
  2. 另外一方面,因爲通常的數據都不會大於10^9,因此當咱們把無窮大加上一個數據時,它並不會溢出(這就知足了「無窮大加一個有窮的數依然是無窮大」),事實上0x3f3f3f3f+0x3f3f3f3f=2122219134,這很是大但卻沒有超過32-bit int的表示範圍,因此0x3f3f3f3f還知足了咱們「無窮大加無窮大仍是無窮大」的需求。
  3. 最後,0x3f3f3f3f還能給咱們帶來一個意想不到的額外好處:若是咱們想要將某個數組清零,咱們一般會使用memset(a,0,sizeof(a))這樣的代碼來實現(方便而高效),可是當咱們想將某個數組所有賦值爲無窮大時(例如解決圖論問題時鄰接矩陣的初始化),就不能使用memset函數而得本身寫循環了(寫這些不重要的代碼真的很痛苦),咱們知道這是由於memset是按字節操做的,它可以對數組清零是由於0的每一個字節都是0,如今好了,若是咱們將無窮大設爲0x3f3f3f3f,那麼奇蹟就發生了,0x3f3f3f3f的每一個字節都是0x3f!因此要把一段內存所有置爲無窮大,咱們只須要memset(a,0x3f,sizeof(a))。

因此在一般的場合下,0x3f3f3f3f真的是一個很是棒的選擇。數組

相關文章
相關標籤/搜索