31

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

const int INF = 0x3f3f3f3f;

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

00111111001111110011111100111111

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

a = min(INF, b + c);

但是,那么所有其他常量都可以。谷歌搜索只显示了很多使用该常量的代码片段,但没有解释或评论。

谁能发现它?

4

3 回答 3

32

我在这里找到了一些证据(中文原文);基本思想是 0x7fffffff 是有问题的,因为它已经是 4 字节有符号整数范围的“顶部”;因此,向其中添加任何内容都会导致负数;0x3f3f3f3f,改为:

  • 仍然很大(0x7fffffff 的数量级相同);
  • 有很大的净空;如果您说整数的有效范围仅限于低于它的数字,您可以将任何“有效正数”添加到它并仍然获得无限(即 something >=INF)。甚至INF+INF不会溢出。这允许它始终“处于控制之下”:

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

  • 此外,正如@Jörg W Mittag 上面注意到的那样,它有一个很好的 ASCII 表示,它允许在查看内存转储时即时发现它,并将它直接写入内存。
于 2013-08-25T12:58:57.217 回答
19

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

有两个原因:

  • 0x3f3f3f3f + 0x3f3f3f3f 不会溢出 int32。为此,有些人使用 100000000(十亿)。
  • 可以通过执行将整数数组设置为无穷大memset(array, 0x3f, sizeof(array))
于 2015-06-03T09:09:32.037 回答
10

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

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

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

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

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

于 2013-08-25T12:53:00.640 回答