聊一聊為什么是 0x3f ?
為什么是 0x3f ?
寫 dijkstra 等等經(jīng)典算法時;我們希望 dist 數(shù)組初始值是 無窮大 的數(shù),常常會用到 memset(dist, 0x3f, sizeof dist) 。為什么要給 dist 賦值為 0x3f3f3f3f 呢?
首先我們看一下 0x3f 有多大。
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- int main()
- {
- int a[1];
- memset(a, 0x3f, 4);
- cout << a[0];
- }
輸出 1061109567 ,是10^9級別的。
memset 按照字節(jié)賦值,因此我們把 4 個 0011 1111 填充到 32 位的 int 上。但問題是,為什么不是 0x4f 或者 0x5f ?
首先 10^9 級別足夠大,其次,也是最重要的,0x3f3f3f3f + 0x3f3f3f3f 等于 0x7e7e7e7e , 不會爆int 。
在很多算法中,我們需要進行諸如 dist[j] > dist[t] + w[t][j] 之類的判斷,如果兩個大于 0x3f3f3f3f 的數(shù)相加,那么后果不堪設(shè)想。因為溢出并不會報錯,算法邏輯復雜,我們往往很難定位真正的錯誤。
附:近期收集了很多 C++ STL 的妙用... 如下圖片的 C++ 確實有點感觸。
筆記主要放在 github/PiperLiu/ACMOI_Journey[1] 的“經(jīng)驗”中。有空一并整理。
此外,memset 對于不同的數(shù)據(jù)類型初始值當然是不同的,有一篇極好的文章:【自用】 memset對于int、long long、float、double 的極值怎么清[2],閱讀原文也可查看。比如 int 對應 0x3f, float 對應 0x4f 。
值得注意的是,我最近在看歪總代碼時,用到初始化 -INF ,直接 memset(a, -0x3f, sizeof a) 也是可以的,無非就是 0x3f 取反加一嘛,從 0011 1111 變?yōu)?1100 0001 。但是相加會爆。
參考資料
[1]github/PiperLiu/ACMOI_Journey: https://github.com/PiperLiu/ACMOI_Journey
[2]【自用】 memset對于int、long long、float、double 的極值怎么清: https://blog.csdn.net/vmurder/article/details/46537613