编程中无穷大常量的设定技巧(转)

转自 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真的是一个很是棒的选择。数组

相关文章
相关标签/搜索