为什么无穷大= 0x3f3f3f3f?

Gab*_*iel 22 c infinity

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

const int INF = 0x3f3f3f3f;
Run Code Online (Sandbox Code Playgroud)

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

00111111001111110011111100111111
Run Code Online (Sandbox Code Playgroud)

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

a = min(INF, b + c);
Run Code Online (Sandbox Code Playgroud)

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

谁能发现它?

Mat*_*lia 25

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

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

    a+=b;
    if(a>INF)
        a=INF;
    
    Run Code Online (Sandbox Code Playgroud)
  • 是一个相等字节的重复,这意味着你可以轻松地memset填充INF;

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

  • 它是`memset`和`INF + INF`属性的最大字节,因为`2*0x40404040`是0x80808080> 0x80000000,这比最大32位int多一个. (4认同)

Ale*_*dru 11

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

有两个原因:

  • 0x3f3f3f3f + 0x3f3f3f3f不会溢出int32.为此一些使用1亿(十亿).
  • 通过这样做,可以将一组int设置为无穷大 memset(array, 0x3f, sizeof(array))


Jör*_*tag 9

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

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

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

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

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