当前位置: 首页 > 知识库问答 >
问题:

平方根2的二进制搜索

石思淼
2023-03-14

我有一个问题,我的二进制搜索算法寻找2的平方根似乎是在一个无限循环中,并永远运行:

num = 2
low = 1
high = num
i = 0
while((i**2) != 2): #was while(low<high): but wasnt working with it either
 i = low + (high - low) / 2;

 sqrt = i * i

 if (sqrt == num):
     print(i)
 elif(sqrt < num):
     low = i
 else:
     high = i
print(sqrt)    

testRoot = 2 ** (.5)
print(testRoot)

我不确定我的while循环是否存在问题。我认为这将是一个非常直接的二进制搜索算法,只需稍加修改即可适应平方根方面。

当运行我的代码时,我似乎无法让它产生任何输出。我不确定代码或编译器是否存在真正的问题,因为我认为我遵循的算法与过去非常接近。

共有3个答案

陈允晨
2023-03-14

两个浮点数之间的相等是一个非常严格的条件,因为2的平方根在小数点后有无限位数。在以下情况下尝试此

while (abs((i ** 2) - 2) > 1e-8)

尹承业
2023-03-14

正如我在最初的评论和所有答案中提到的,2的平方根是非理性的。每一个不是完美平方的整数的平方根都是无理的,所以2在这方面并不特别。重要的是,x**2==2对于任何具有有限精度的x(因为有限精度是表示数字是有理数的另一种方式)来说永远不会是真的。

其他答案建议搜索,直到达到某个固定的、预先确定的精度。这很有效,特别是如果你提前知道答案的二进制数量级,那么你可以将结果的精度设置为最后一位。

我想建议一种更自然的方法。您可以检查中心值是否正好等于其中一个边界。这意味着,在当前的猜测中,两个边界之间的差异有一半表示精度不到一位数。您对中心的措辞已经正确:i=low(high-low)/2可以使用=lowhigh进行比较,而i=(low-high)/2可能不能。这是因为high-low的精度大于或等于任一边界的精度,而low-high可能会丢失一些数字。

因此,以下是我的建议:

num = 2
low = 1
high = num
guess = low + (high - low) / 2
count = 0
while guess != low and guess != high:
    sqr = guess * guess

    if sqr == num:
        break
    elif(sqr < num):
        low = guess
    else:
        high = guess

    guess = low + (high - low) / 2
    count += 1
else:
    if abs(low * low - num) < abs(high * high - num):
        guess = low
    else:
        guess = high

print(count, ':', sqr)
print(num ** (.5), '~=', guess)

我添加了count以进行验证。在52次迭代中获得结果,精度在1位数以内:

52 : 2.0000000000000004
1.4142135623730951 ~= 1.4142135623730951 

对边界的最后检查(while中的else子句)可确保您获得最接近所需结果的边界,而不管您先点击哪个边界。

收敛是合理的:IEEE-754格式的64位浮点数尾数中有53位,因此有必要将搜索空间精确地减半很多次才能得到结果(第一次是在循环之外)。

这是我用来测试的片段:https://ideone.com/FU9r82

范承志
2023-03-14

问题是,在浮点数上使用=几乎总是一个糟糕的做法,对此有各种各样的问题。您应该用abs(a-b)替换比较

我修改后的代码看起来像这样(Python 3),如果你想要更精确,用更小的数字替换1e-6。但是请注意,“太精确”是不明智的,如果您希望循环停止,建议精度为1.0e-15或更大,因为浮点数本身有精度限制。

num = 2
low = 1
high = num
i = 0
while abs((i**2) - num) > 1e-6:  # Note
    i = low + (high - low) / 2
    sqrt = i * i

    if abs(sqrt - num) < 1e-6:  # Note
        print(i)
    elif(sqrt < num):
        low = i
    else:
        high = i
print(sqrt)

testRoot = 2 ** (.5)
print(testRoot)
 类似资料:
  • 上面是工作代码段。我有以下问题。事先谢谢你的帮助。;-) while(end-start>1)为什么这里需要1?就因为返回的意思是int? 如果我们将while循环从while(end-start>1)更改为while(end>start),我们必须使end=mid-1;和start=mid+1,对吗?还有一步,不知道这是不是也是因为返回类型是整数? 为什么不能返回End?或(int)(开始+结束

  • 我用java创建了一个二进制搜索树,允许用户向该树添加节点 这是我在java中实现的二叉树,它在创建时接受根节点,然后自动计算出它应该将子节点添加到树的左侧或右侧。 但是当我尝试使用

  • 我正在一个实验室工作,该实验室要求我为二进制搜索树创建一个删除方法。这是我的remove方法的代码。 运行代码时得到的输出是: 移除90后的树。70 80 85 98 100 120 移除70. 80 85 98 100 120后的树 移除85后的树。80 98 100 120 移除98后的树。80 100 120 移除80后的树。100 120 移除120后的树。100 移除100后的树。100

  • 我在C中实现了一个二进制搜索树。 对于delete方法,除了最后一种情况外,其他情况都可以使用,即唯一的树是父树,并且它指向两个空的子树。现在的问题是:我希望在删除子树后,打印出父树的左子树和右子树等于什么。它们和父项都应该为NULL,但是当我试图输出这些值时,我得到了一个状态访问冲突。 下面是有关删除的代码。我希望删除父节点,并设置树- 主要:

  • 我正在尝试删除我的二叉查找树的根,以便我可以更新它的值,但这种方法不能做到这一点。我的想法是删除根,然后将其再次插入二叉查找树中,但使用另一个值。它适用于树中的每个节点,但不是我无法删除它的根本原因。有人知道为什么会发生这种情况吗?谢谢。 这是我调用方法删除任何节点的主代码,在这种情况下,我想删除根。

  • 我和我的搭档正在为数据结构实现二进制搜索树 在我们的测试案例中,我们没有得到我们预期的结果。我们最初创建了一个空的BinarySearchTree,并调用add方法。从这里,我们将一个整数对象(10)传递给该方法。完成此操作后,应该调用递归addItem方法。thisRoot当前应该引用null(因为我们创建了一个空的BinarySearchTree),因此thisRoot现在应该引用新的Bina