为什么M=L+;((R-L)/2)而不是M=(L+;R)/2避免在C++;? 你好,我在看C++的解决方案“假设一个排序的数组在某个未知的旋转点之前旋转(即,0 1×2 4 5 6 7可能变成4 5 6 7 0 0)。你如何找到一个旋转数组中的元素?你可以假设数组中没有重复。” int旋转的二进制搜索(int A[],int N,int键){ int L=0; int R=N-1; 而(L

为什么M=L+;((R-L)/2)而不是M=(L+;R)/2避免在C++;? 你好,我在看C++的解决方案“假设一个排序的数组在某个未知的旋转点之前旋转(即,0 1×2 4 5 6 7可能变成4 5 6 7 0 0)。你如何找到一个旋转数组中的元素?你可以假设数组中没有重复。” int旋转的二进制搜索(int A[],int N,int键){ int L=0; int R=N-1; 而(L,c++,C++,因为它确实 让我们假设您正在使用无符号字符(当然,这同样适用于较大的整数) 如果L为100,R为200,则第一个版本为: M = (100 + 200) / 2 = 300 / 2 = 22 100+200溢出(因为最大的无符号字符是255),得到100+200=44(无符号编号加法) 第二,另一方面: M = 100 + (200-100) / 2 = 100 + 100 / 2 = 150 没有溢出 正如@user2357112在评论中指出的,没有免费午餐。如果L为负值,第二个版本可能无

因为它确实

让我们假设您正在使用无符号字符(当然,这同样适用于较大的整数)

如果L为100,R为200,则第一个版本为:

M = (100 + 200) / 2 = 300 / 2 = 22
100+200溢出(因为最大的无符号字符是255),得到100+200=44(无符号编号加法)

第二,另一方面:

M = 100 + (200-100) / 2 = 100 + 100 / 2 = 150
没有溢出


正如@user2357112在评论中指出的,没有免费午餐。如果L为负值,第二个版本可能无法工作,而第一个版本可能无法工作。

不确定,但如果int的最大限制为100

R=80 & L = 40
then, 
M=(L+R)/2
M=(120)/2, here 120 is out limits if our integer type, so this causes overflow
但是,

M = L + ((R - L) / 2)  
M = 80 +((40)/2)
M = 80 +20
M =100.
因此,在这种情况下,我们永远不会遇到超过整数类型限制的值。因此,从理论上讲,这种方法永远不会遇到溢出


我希望这个类比能有所帮助。这个评论是错误的,原因有很多

  • 对于特定问题,溢出的风险可能为零
  • 重新排序计算不能保证编译器将按该顺序执行它们
  • 如果存在一个排序可能导致溢出的值范围,则存在另一个重新排序的计算将导致溢出的值范围
  • 如果溢出可能是一个问题,那么应该显式地控制它,而不是隐式地控制它
这是断言的最佳位置。在这种情况下,只有
N
小于
int
的最大正范围的一半时,算法才有效,所以在断言中说它

如果要求算法适用于整个正负范围的
signed int
,则应在断言中显式测试该范围,并应通过引入序列点(如分成两条语句)对计算进行排序


做对这件事很难。数值计算充满了这些东西。如果可能的话,最好避免。不要接受随机的建议(即使是这样!)不做你自己的研究。

它避免了这个具体实现中的溢出,这个具体实现在保证
L
R
非负的情况下运行,并且
L为
M
L
使用一些较大的值,你会很快发现这一点o回答这样的问题,并沐浴在荣耀中。(排序程序现已确定)请注意,对于
L
R
可能为负值的情况,这并不能避免溢出,因为
R-L
也可能溢出。您需要跳过一些令人惊讶的冗长循环以获得安全的通用整数平均值。这是Bentley的错误。(只有像宾利这样有造诣的人才能有一个以他的名字命名的虫子,而不是一个耻辱)。除了你给L加了80外,其他都是有效的。:P
M = L + ((R - L) / 2)  
M = 80 +((40)/2)
M = 80 +20
M =100.