2013-08-25 39 views
17

在某些情况下,通常使用足够大的整数值来表示无穷大。我通常使用最大的可表示的正/负整数。这通常会产生更多的代码,因为您需要在几乎所有算术运算之前检查其中一个操作数是否为无穷大,以避免溢出。有时需要饱和整数算术。出于这个原因,有些人使用较小的值来表示无穷大,可以多次添加或乘数而不会溢出。是什么令我着迷的是,这是非常常见的,看(特别是在编程竞赛):为什么infinity = 0x3f3f3f3f?

const int INF = 0x3f3f3f3f; 

为什么是这个数字特别?它的二进制表示是:

00111111001111110011111100111111 

我在这里没有看到任何特别有趣的属性。我发现输入很容易,但如果这是原因,几乎所有的东西都会(0x3e3e3e3e,0x2f2f2f2f等)。它可以添加一次没有溢出,它允许:

a = min(INF, b + c); 

但是,所有其他常数会做,然后。谷歌搜索只显示了很多使用该常量的代码片段,但没有解释或评论。

任何人都可以发现它吗?

+3

整数设置为无穷大数组你有一个通用的上下文中使用这个任何具体的例子(而不是一个专门的算法,其中它可能是有意义内)? – Mat

+0

我将其标记为C,因为快速Google搜索只能找到使用该常量的C代码。随意重新标记。 – JJJ

+1

@Mat:例如,可以采用计算图中最短路径的算法。从起始顶点到不可达顶点的距离在理论上是无穷大的。你需要一些方式来表示(但使用浮点数会是一个矫枉过正)。 可能有一些使用此算法的算法非常不同。我举了一个具体的例子,但是当你用伪代码写“无穷大”的时候,这个技巧很方便。 – Gabriel

回答

19

我发现了一些关于这个hereoriginal content中文)的证据;基本思想是0x7fffffff有问题,因为它已经是4字节签名整数范围的“顶部”;所以,增加任何东西都会导致负数; 0x3f3f3f3f,而不是:

  • 仍然相当大(相同数量级的0x7fffffff);
  • 有很大的空间;如果你说整数的有效范围限制在它下面的数字,你可以添加任何“有效的正数”,并仍然是无限的(即>=INF)。即使INF+INF也不会溢出。这允许保持它始终“在控制之下”:

    a+=b; 
    if(a>INF) 
        a=INF; 
    
  • 等于字节的重复,这意味着你可以很容易地memset东西INF;

  • 此外,正如@JörgW Mittag在上面注意到的,它具有很好的ASCII表示形式,可以在查看内存转储时即时发现它,并将其直接写入内存。
+2

它是带有memset和INF + INF的最大字节,属性,因为'2 * 0x40404040'是0x80808080> 0x80000000,这比最大32位int多一个。 –

9

0x3f3f3f3f是字符串????的ASCII表示形式。

Krugle在其整个数据库中发现该常量的48个实例。这些实例中的46个在Java项目中,在那里它被用作一些图形操作的位掩码。

1项目是一个操作系统,它用来表示未知的ACPI设备。

1项目再次是Java图形的位掩码。

因此,在由Krugle索引的所有项目中,由于它的位模式,它被使用了47次,一次是因为它的ASCII解释,而不是一次性作为无限的表示。

8

我可能也可能不是最早发现0x3f3f3f3f的人之一。我在2004年发表了罗马尼亚文章(http://www.infoarena.ro/12-ponturi-pentru-programatorii-cc#9),但自2002年以来我一直在使用这个值,至少在编程比赛中。

有两个原因:

  • 0x3f3f3f3f + 0x3f3f3f3f不会溢出INT32。为此有些使用1亿(十亿)。
  • 一个可以通过做memset(array, 0x3f, sizeof(array))
相关问题