为什么无穷大等于0x3f3f3f3f?

32

在某些情况下,一般使用足够大的整数值来表示无穷大。我通常使用最大可表示的正/负整数。这通常会产生更多的代码,因为你需要在几乎所有算术运算之前检查操作数是否为无穷大,以避免溢出。有时候希望有饱和整数算术。为此,有些人使用较小的无穷大值,可以多次添加或相乘而不会发生溢出。让我感到好奇的是,在编程比赛中经常看到这种用法:

const int INF = 0x3f3f3f3f;

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

00111111001111110011111100111111

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

a = min(INF, b + c);

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

有人能找出来吗?


3
你有没有任何具体的例子,说明这个东西在通用环境下被使用过(而不是在专门的算法中,那里它可能有意义)? - Mat
我将此标记为C,因为快速的谷歌搜索只找到使用该常量的C代码。请随意重新标记。 - JJJ
2
@Mat:例如,取任何计算图中最短路径的算法。从起始顶点到无法到达的顶点的距离在理论上是无限的。你需要一些方式来表示它(但使用浮点数会过度)。可能有很多不同的算法示例使用这种技术。我给出了一个具体的例子,但当你在伪代码中写“无穷大”时,这种技巧非常方便。 - Gabriel
2
具体的例子,而不是“这可能被用于假设”。你声称这些非常普遍,请提供一些真实世界的例子链接。 - Mat
1
@Mat:抱歉,我认为我的说法确实太过强烈。这在“现实世界”可能不常见,但在编程比赛中仍然“非常普遍”:http://goo.gl/PMCUNL - Gabriel
3个回答

35
我在这里中文原文)找到了一些证据;基本思路是0x7fffffff存在问题,因为它已经是4字节有符号整数范围的“顶端”,所以将任何东西添加到它都会导致负数;相反,应该使用0x3f3f3f3f:
  • is still quite big (same order of magnitude of 0x7fffffff);
  • has a lot of headroom; if you say that the valid range of integers is limited to numbers below it, you can add any "valid positive number" to it and still get an infinite (i.e. something >=INF). Even INF+INF doesn't overflow. This allows to keep it always "under control":

    a+=b;
    if(a>INF)
        a=INF;
    
  • is a repetition of equal bytes, which means you can easily memset stuff to INF;

  • also, as @Jörg W Mittag noticed above, it has a nice ASCII representation, that allows both to spot it on the fly looking at memory dumps, and to write it directly in memory.

4
这是拥有memsetINF+INF属性的最大字节数,因为2*0x40404040等于0x80808080,大于32位整数的最大值0x80000000,因此比其多1。 - Evgeni Sergeev

20

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

这个值被使用的原因有两个:

  • 0x3f3f3f3f + 0x3f3f3f3f不会导致int32溢出。有些人使用100000000(十亿)来代替。
  • 通过执行memset(array, 0x3f, sizeof(array)),可以将一个int数组设置为无穷大。

12

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

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

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

另外1个项目再次用作Java图形的位掩码。

因此,在Krugle索引的所有项目中,它由于其比特模式被使用了47次,由于其ASCII解释被使用了1次,并且没有一次作为无限大的表示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接