Java 中点公式溢出错误

Java 中点公式溢出错误,java,algorithm,binary-search,Java,Algorithm,Binary Search,我正在学习算法/大o,我只是对此感到好奇 使用 mid = (low+high)/2; 为了获得二进制搜索的中点,通常不鼓励使用算法,因为可能会出现溢出错误。为什么这会导致溢出错误发生,以及如何发生 mid = low + (high-low)/2; 防止这个错误 谢谢。在第一种情况下,如果low和high都足够大(例如,如果两者都等于2^30+1/或更大),则计算的值(low+high)可能太大,无法放入整数中。在第二种情况下,不计算(低+高),只需执行一个小技巧,然后遍历表达式(高-

我正在学习算法/大o,我只是对此感到好奇

使用

 mid = (low+high)/2;
为了获得二进制搜索的中点,通常不鼓励使用算法,因为可能会出现溢出错误。为什么这会导致溢出错误发生,以及如何发生

 mid = low + (high-low)/2;
防止这个错误


谢谢。

在第一种情况下,如果low和high都足够大(例如,如果两者都等于2^30+1/或更大),则计算的值(low+high)可能太大,无法放入整数中。在第二种情况下,不计算(低+高),只需执行一个小技巧,然后遍历表达式(高-低),该表达式相对于int溢出更安全


但是,如果没有一个数组的大小大于2^30(无论如何,这是一个非常大的数组),我看不出即使使用第一个表达式,也会遇到int溢出。因此,在大多数情况下,我只使用第一种,不用担心。

每个基本数据类型都有一个最大值和最小值。当您超过该数据类型的最大值或最小值时,它将分别换行为最小值或最大值

mid = (low+high)/2;
在这种情况下,如果
低+高>最大值
,您将得到奇怪的结果

这里有一个有趣的测试,你可以试试

int high = Integer.MAX_VALUE;
int low = 3*Integer.MAX_VALUE/4;
int mid = (high+low)/2;
System.out.println(mid); // -805306369 

通过更改数学,您可以通过减去它们而不是添加它们来消除执行最大值或最小值的可能性。

让我们假设整数的最坏情况。 如果我们从更大的角度来看,我们确信mid=(低+高)/2永远不会产生溢出。假设low=2ˆ31-1和high=2ˆ31-1(最高整数值),则总计算将为[2*(2ˆ31-1)]/2=2ˆ31-1。(int可以容纳的最大数字)

然而,我们计算它的方式很重要

  • 如果它是用(低+高)/2计算的,那么在我们的情况下它只会给出一个溢出,因为首先它会尝试求和低(2ˆ31) -1)和高(2ˆ31-1)和BAM。2*(2ˆ31-1)为溢流。它不能将其除以二,因为它不能将该值最初存储在int中

  • 如果使用low+(high-low)/2计算,则不能给出溢出。 这样想,低+(高-低)/2=(低+x),其中x=(高-低)/2。为了产生溢出,我们应该为双方选择大的数字(在我们的情况下,int是最大的)。然而,如果我们选择最大的低,那么x将是最小的(因为我们从x的高减去低),反之亦然


您知道溢出是什么吗?可能是一个很好的开始。是的,当堆栈太满以至于无法分配任何数据时。@Hmir不是这样。这里的单词是关于类型溢出,而不是关于堆栈溢出。这是溢出的一种形式(堆栈溢出)。在这个场景中,您关注的是整数overflow@clcto哦,好吧,我明白了,谢谢?如果
low=high=Integer.MAX
,该怎么办?这和数组的大小有什么关系?@clcto没什么特别的,同样的。。。你得到了溢出。低和高是数组索引,OP是指二进制搜索;这就是它与数组大小的关系。