为什么无穷大总是0x3f3f3f3f而不是0x7fffffff?

如果问题中各数据的范围明确,那么无穷大的设定不是问题,在不明确的情况下,很多程序员都取0x7fffffff作为无穷大,因为这是32-bit int的最大值。如果这个无穷大只用于一般的比较(比如求最小值时min变量的初值),那么0x7fffffff确实是一个完美的选择,但是在更多的情况下,0x7fffffff并不是一个好的选择。

且听我慢慢道来,为什摸0x7fffffff为什摸不是个好的选择

1.但在很多情况下,0x7fffffff会出现错误,比如溢出。

   这样两个无穷大数相加会变成负数,还有如在做dijkstra求最短路时,当做松弛操作,判断if (d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v],

   若u到v没有路劲w[u][v]=0x7fffffff,这样d[u]+w[u][v]会变成负数,这就产生了错误

   无穷大加无穷大依然是无穷大”,至少两个无穷大相加不应该出现灾难性的错误,这一点上0x7fffffff依然不能满足我们

    if (d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v];

     准确来说,0x7fffffff不能满足“无穷大加一个有穷的数依然是无穷大”这个条件,它会变成了一个很小的负数。

     来个小测试及更明白了

#include<stdio.h>
#include<string.h>
#define MAX1 0x7fffffff
#define MAX2 0x3f3f3f3f
int a[3];
int main()
{
	memset(a,0x3f,sizeof(a));
	printf("%d\n",MAX1);
	printf("%d\n",MAX1*2);
	printf("%d\n",MAX2);
	printf("%d\n",MAX2*2);
	for(int i=0;i<3;i++)
	printf("%d ",a[i]);
	printf("\n");
	return 0;
}

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))。

所以在通常的场合下,const int INF = 0x3f3f3f3f;真的是一个非常棒的选择。

猜你喜欢

转载自blog.csdn.net/mlm5678/article/details/82729974