聊一聊为什么是 0x3f ?

开发 前端
写 dijkstra 等等经典算法时;我们希望 dist 数组初始值是 无穷大 的数,常常会用到 memset(dist, 0x3f, sizeof dist) 。为什么要给 dist 赋值为 0x3f3f3f3f 呢?

 [[419429]]

为什么是 0x3f ?

写 dijkstra 等等经典算法时;我们希望 dist 数组初始值是 无穷大 的数,常常会用到 memset(dist, 0x3f, sizeof dist) 。为什么要给 dist 赋值为 0x3f3f3f3f 呢?

首先我们看一下 0x3f 有多大。

  1. #include <iostream> 
  2. #include <cstring> 
  3. #include <algorithm> 
  4. using namespace std; 
  5.  
  6. int main() 
  7.     int a[1]; 
  8.     memset(a, 0x3f, 4); 
  9.     cout << a[0]; 

输出 1061109567 ,是10^9级别的。

memset 按照字节赋值,因此我们把 4 个 0011 1111 填充到 32 位的 int 上。但问题是,为什么不是 0x4f 或者 0x5f ?

首先 10^9 级别足够大,其次,也是最重要的,0x3f3f3f3f + 0x3f3f3f3f 等于 0x7e7e7e7e , 不会爆int 。

在很多算法中,我们需要进行诸如 dist[j] > dist[t] + w[t][j] 之类的判断,如果两个大于 0x3f3f3f3f 的数相加,那么后果不堪设想。因为溢出并不会报错,算法逻辑复杂,我们往往很难定位真正的错误。

附:近期收集了很多 C++ STL 的妙用... 如下图片的 C++ 确实有点感触。

笔记主要放在 github/PiperLiu/ACMOI_Journey[1] 的“经验”中。有空一并整理。

此外,memset 对于不同的数据类型初始值当然是不同的,有一篇极好的文章:【自用】 memset对于int、long long、float、double 的极值怎么清[2],阅读原文也可查看。比如 int 对应 0x3f, float 对应 0x4f 。

值得注意的是,我最近在看歪总代码时,用到初始化 -INF ,直接 memset(a, -0x3f, sizeof a) 也是可以的,无非就是 0x3f 取反加一嘛,从 0011 1111 变为 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

责任编辑:武晓燕 来源: Piper蛋窝
相关推荐

2021-12-29 07:18:20

重构工具资源

2021-12-09 10:17:25

部署实战Linux

2023-10-24 15:56:23

2024-04-16 08:20:01

React属性钻取状态管理

2023-03-05 18:40:39

iptables防火墙软件

2021-06-29 08:45:55

逻辑变量法函数

2021-05-25 05:28:05

uniCloud前端项目

2023-09-22 17:36:37

2021-01-28 22:31:33

分组密码算法

2020-05-22 08:16:07

PONGPONXG-PON

2022-11-09 08:05:15

JavaScriptsuper()

2018-06-07 13:17:12

契约测试单元测试API测试

2023-05-15 08:38:58

模板方法模式

2021-01-29 08:32:21

数据结构数组

2022-08-08 08:25:21

Javajar 文件

2021-08-04 09:32:05

Typescript 技巧Partial

2019-02-13 14:15:59

Linux版本Fedora

2018-11-29 09:13:47

CPU中断控制器

2021-02-06 08:34:49

函数memoize文档

2023-07-06 13:56:14

微软Skype
点赞
收藏

51CTO技术栈公众号