找到任意大数的算法

时间:2012-04-02 02:47:48

标签: algorithm

这是我一直在考虑的事情:假设你有一个数字,x,可以是无限大,你必须找出它是什么。所有你知道的是,如果另一个数字y大于或小于x。什么是找到x的最快/最好的方法?

一个邪恶的对手选择了一个非常大的数字......说:

int x = 9^9^9^9^9^9^9^9^9^9^9^9^9^9^9

并提供isXisBiggerThanXisSmallerThanx个功能。示例代码可能如下所示:

int c = 2
int y = 2
while(true)
    if isX(y) return true
    if(isBiggerThanX(y)) fn()
    else y = y^c

其中fn()是一个函数,一旦找到数字y(大于x)就会确定x(比如将数字除以一半并进行比较,然后重复)。问题是,由于x是任意大的,因此使用常数来增加y似乎是一个坏主意。

这是我一直想知道的一段时间,我想听听其他人的想法

7 个答案:

答案 0 :(得分:6)

使用二进制搜索,就像通常的“尝试猜测我的号码”游戏一样。但由于没有有限的上限点,我们会在第一阶段找到合适的上端点:

  • 最初任意设置上端点(例如1000000,虽然1或1 ^ 100也可以工作 - 给定无限空间可用,所有有限值同样不成比例)。
  • 将神秘数字X与高端点进行比较。
  • 如果不够大,请加倍,然后重试。
  • 一旦上端点大于神秘数字,继续进行正常的二分查找。

第一阶段本身类似于二元搜索。不同之处在于,不是每一步都将搜索空间减半,而是将其翻倍!每个阶段的成本为O(log X)。一个小的改进是在每个加倍步骤设置低端点:我们知道X至少与前一个高端点一样高,所以我们可以将它重用为低端点。搜索空间的大小在每一步仍然翻倍,但最终它将是原来的一半。二进制搜索的成本只会减少一步,因此其总体复杂性保持不变。

一些注释

回应其他评论时的几点说明:

这是一个有趣的问题,计算机科学不只是关于在物理机器上可以做什么。只要问题可以正确定义,就值得提出并思考。

数字的范围是无限的,但任何可能的神秘数字都是有限的。所以上面的方法最终会找到它。 最终定义,例如,对于任何可能的有限输入,算法将在有限数量的步骤内终止。然而,由于输入是无界的,步数也是无限的(只是在每种特定情况下,它将“最终”终止。)

答案 1 :(得分:3)

如果我正确地理解了你的问题(建议我不这样做),你问的是如何解决“从1到10中选择一个数字”,除了代替10,上限是无穷大。

如果您的数字空间真的无限,则以下情况属实:

  • 该值永远不会保留在任何物理硬件上的int(或任何其他数据类型)
  • 你永远不会找到你的号码

如果空间非常大但受到限制,我认为你能做的最好的就是二元搜索。从数字范围的中间开始。如果所需的数字变得更高或更低,则将该数字空间的一半除去,并重复直到找到所需的数字。

在您建议的实施中,您会引发y ^ c。然而,无论选择多大c,它都不会在无限空间内移动针。

答案 2 :(得分:1)

无限不是一个数字。因此,即使使用计算机也无法找到它。

答案 3 :(得分:1)

这很有趣。多年来我一直在想同样的事情,尽管我从来没有听过其他人提出这个问题。

就像您的方案一样简单,它似乎仍然提供的信息不足以允许选择最佳策略。所有人都可以选择合适的启发式方法。我的启发式方法是加倍y,但我认为我更喜欢你。你们加倍log(y)

启发式的优点在于,只要整数适合计算机的内存,它就会在对数时间内找到合适的y

反的问题。找到y后,您将如何处理?

答案 4 :(得分:1)

我同意使用二进制搜索,但我相信ONE-SIDED二进制搜索会更合适,因为这里的复杂性不会是O(log n)[其中n是允许数字的范围],但是(log k) - 其中k是对手选择的数字。

这将如下工作:(伪代码)

k = 1;

while( isSmallerThanX( k ) )
{
   k = k*2;
}

// At this point, once the loop is exited, k is bigger than x
// Now do normal binary search for the range [ k/2, k ] to  find your number :)

所以即使允许的范围是无穷大,只要你的数字是有限的,你应该能够找到它:)

答案 5 :(得分:1)

如果对手只使用更好的范例(例如,被压抑),那么tetration的方法可以保证花费比宇宙年龄更长的时间来找到答案。这就是你应该这样做的方式:

  1. 您只能使用数字的符号表示来执行此操作,因为命名一个计算机无法以浮点表示形式存储的数字是微不足道的,即使它使用了任意精度算术及其所有内存。
  2. 必读:http://www.scottaaronson.com/writings/bignumbers.html - 这几乎总结了
  3. 您如何代表一个号码?您可以通过一个程序来表示它,如果运行完成,将打印出该数字。即使这样,您的计算机也无法计算BusyBeaver(10 ^ 100)(如果您指定的程序大小为1 TB,这个远远超过有限时钟周期的最大数量,它可以在没有永久循环的情况下运行)。您可以看到,我们可以轻松地让计算机打印出1 0 0 ...每个时钟周期,使其可以说的最大数量(如果我们等待的时间几乎是永恒的话)是10 ^ BusyBeaver(10 ^ 100)。如果你允许它说更复杂的表达式,如eval(someprogram),power-towers,Ackermann的函数,无论如何 - 那么我相信这并不比将原来的10 ^ 100增加一些常数与你描述过(加上一些对数解释因子,见Kolmogorov复杂性)。
  4. 所以让我们用另一种方式构建:

    你的对手选择一个有限的可计算数字,并通过计算它给你一个函数告诉你数字是否更小/更大/相等。他还给你一个输出的表示(在一个理智的世界,这将是“你只能打印像99999这样的数字”,但他可以使它更复杂;它实际上并不重要)。 继续以位为单位测量此函数的大小。

    现在,使用您自己的函数回答,该函数是其函数(以位为单位)的两倍,并打印出最大数字,同时保持代码长度小于2N位。 (你使用他选择的相同表示法:在一个你只能打印出像“99999”这样的数字的世界里,这就是你所做的。如果你能定义函数,它会稍微复杂一点。)

答案 6 :(得分:0)

我不明白这里的目的,但我这就是我的想法:

阅读你的评论,我想你不是在寻找无限大的数字,而是寻找“超大数”。无论数字是多少,都会有一个很大的数字。的数字。你如何得到它们,不是问题。记住这一点:

不需要复杂的计算。只需在数字键盘上键入随机键即可拥有超大号,然后让程序随机添加/删除/修改该数字的数字。你得到一个非常大的数字列表 - 从中​​选择任何一个。

例如:3672036025039629036790672927305060260103610831569252706723680972067397267209 and keep modifying/adding digits to get more numbers

PS:如果你清楚地说出问题的目的,我们或许可以给出更好的答案。