0x3f3f3f3f常量在程式設計中的妙用

2021-09-24 18:24:04 字數 939 閱讀 2718

今天做了一下一道多源最短路徑的問題,用弗洛伊德演算法的,五分鐘敲完,交一下發現wa了,

調了半天才發現初始化鄰接矩陣的inf設定成2147483647(2^31-1)大數相加的時候會溢位,變成很小的負數

為了解決這個問題,我們就在想,要找到這樣乙個大數,滿足加上乙個常數依然是無窮大之外,我們的常量還應該滿足「無窮大加無窮大依然是無窮大」,至少兩個無窮大相加不應該出現災難性的錯誤,這一點上2147483647(0x7fffffff)依然不能滿足我們

到網上找了下,發現很多大牛都是用0x3f3f3f3f這個常量,究竟這樣做有什麼優點呢?

0x3f3f3f3f的十進位制是1061109567,也就是10^9級別的(和0x7fffffff乙個數量級),而一般場合下的資料都是小於10^9的,所以它可以作為無窮大使用而不致出現資料大於無窮大的情形。

另一方面,由於一般的資料都不會大於10^9,所以當我們把無窮大加上乙個資料時,它並不會溢位(這就滿足了「無窮大加乙個有窮的數依然是無窮大」),事實上0x3f3f3f3f+0x3f3f3f3f=2122219134,這非常大但卻沒有超過32-bit int的表示範圍,所以0x3f3f3f3f還滿足了我們「無窮大加無窮大還是無窮大」的需求。

最後,0x3f3f3f3f還能給我們帶來乙個意想不到的額外好處:如果我們想要將某個陣列清零,我們通常會使用memset(a,0,sizeof(a))這樣的**來實現(方便而高效),但是當我們想將某個陣列全部賦值為無窮大時(例如解決圖論問題時鄰接矩陣的初始化),就不能使用memset函式而得自己寫迴圈了(寫這些不重要的**真的很痛苦),我們知道這是因為memset是按位元組操作的,它能夠對陣列清零是因為0的每個位元組都是0,現在好了,如果我們將無窮大設為0x3f3f3f3f,那麼奇蹟就發生了,0x3f3f3f3f的每個位元組都是0x3f!所以要把一段記憶體全部置為無窮大,我們只需要memset(a,0x3f,sizeof(a))。

關於 0x3f3f3f3f 的問題

0x3f3f3f3f是乙個很有用的數值,它是滿足以下兩個條件的最大整數。1 整數的兩倍不超過 0x7f7f7f7f,即int能表示的最大正整數。2 整數的每8位 每個位元組 都是相同的。我們在程式設計中經常需要使用 memset a,val,sizeof a 初始化乙個陣列a,該語句把數值 val ...

0x3f3f3f3f(無窮大數)

一般定義無窮大數都是inf 99999999,或者0x7f ff ff ff,但是有的時候inf過大,雖然保證了沒有數超過它,但是在需要加上乙個數的時候,inf a可能會導致溢位,最終變成乙個負數。而0x3f3f3f3f的數量級也1e9的,一般題不會給超過1e9的數 在把它當成無窮大的時候,兩個0x...

為何INF設定為0x3f3f3f3f?

在演算法競賽中,我們常常需要用到乙個 無窮大 的值,對於我來說,大多數時間我會根據具體問題取乙個99999999之類的數 顯得很不專業啊!在網上看別人 的時候,經常會看到他們把inf設為0x7fffffff,奇怪為什麼設乙個這麼奇怪的十六進製制數,一查才知道,因為這是32 bit int的最大值。如...