为什么无穷大= 0x3f3f3f3f?

时间:2013-08-25 12:33:43

标签: c infinity

在某些情况下,通常使用足够大的整数值来表示无穷大。我通常使用最大可表示的正/负整数。这通常会产生更多代码,因为您需要在几乎所有算术运算之前检查其中一个操作数是否为无穷大,以避免溢出。有时需要进行饱和整数运算。出于这个原因,有些人使用较小的无穷大值,可以添加或倍增几次而不会溢出。引起我兴趣的是,这一事实非常普遍(特别是在编程竞赛中):

const int INF = 0x3f3f3f3f;

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

00111111001111110011111100111111

我在这里看不到任何特别有趣的财产。我看到输入很容易,但如果这是原因,几乎任何事情都可以(0x3e3e3e3e,0x2f2f2f2f等)。它可以添加一次而不会溢出,这允许:

a = min(INF, b + c);

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

有人能发现它吗?

3 个答案:

答案 0 :(得分:22)

我发现了一些关于here(中文original content)的证据;基本的想法是0x7fffffff是有问题的,因为它已经是4字节有符号整数范围的“顶部”;因此,添加任何内容会导致负数; 0x3f3f3f3f,而不是:

  • 仍然很大(相同数量级的0x7fffffff);
  • 有很多空间;如果你说整数的有效范围限于低于它的数字,你可以添加任何“有效正数”并仍然得到无限(即>=INF)。即使INF+INF也不会溢出。这样可以使其始终处于“受控制”状态:

    a+=b;
    if(a>INF)
        a=INF;
    
  • 是相等字节的重复,这意味着您可以轻松memset填充INF;

  • 另外,正如@JörgWMittag在上面注意到的那样,它有一个很好的ASCII表示,允许它们在运行中查看内存转储,并将其直接写入内存。

答案 1 :(得分:9)

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

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

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

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

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

答案 2 :(得分:8)

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

有两个原因:

  • 0x3f3f3f3f + 0x3f3f3f3f不会溢出int32。对于这个,一些使用100000000(十亿)。
  • 可以通过memset(array, 0x3f, sizeof(array))
  • 将一组ints设置为无穷大