在许多算法中,我看到人们使用两种不同的方法来获得中间点。
(低+高)/2
低+(高-低)/2
我大多见过第二种方法,例如在快速排序中。找到两个数字中间的最佳方法是什么?为什么?

最佳答案

这完全取决于上下文,但我将对第2个案例进行说明并解释原因。
我们首先假设您选择1号案例,即:

(LOW + HIGH) / 2

这看起来完全合理,从数学上讲,确实如此。让我们插入两个数字并查看结果:
(12345 + 56789) / 2

结果是34567看起来还好吧?
现在,问题是在计算机中并没有那么简单。您还需要处理一个名为data types的问题。通常用位数来表示换句话说,你可能有一个32位的数字,或者16位的数字,或者64位的数字,等等。
所有这些都有所谓的法律价值范围,即“这些类型将持有什么样的价值”一个8位数字,无符号(这意味着它不能为负)可以保持2到8个不同值的幂,即256。16位无符号值可以包含65536个值,或0到65535的范围。如果值是有符号的,则它们从-half变为+half-1,这意味着8位有符号值将从-128变为+127,有符号16位值将从-32768变为+32767。
现在我们回到原来的公式。如果我们用于计算的数据类型不足以容纳LOW + HIGH,该怎么办?
例如,假设我们使用了16位有符号值,我们仍然得到这个表达式:
(12345 + 56789) / 2

12345可以保持在16位值(小于65536),与56789相同,但结果如何?12345和56789相加的结果是69134,大于65535(最高的无符号16位值)。
那会发生什么呢?有两种结果:
它将溢出,这意味着它将从0开始并向上计数,这意味着它实际上将以3598(123456 + 56789) - 65536的结果结束。
它将抛出一个异常或类似的异常,导致程序崩溃并出现溢出问题。
如果我们得到第一个结果,那么(12345 + 56789)/2就变成3598/2或1799显然不正确。
那么,如果我们采用另一种方法:
12345 + (56789-12345)/2

首先,让我们做一个括号:56789-12345等于44444,一个可以保存在16位数据类型中的数字。
添加12345 + 44444可以得到56789,这个数字也可以保存在16位数据类型中。
56789除以2得到28934.5因为我们可能在这里处理“整数”,所以我们得到28934(通常,除非您的特定世界结束)。
因此,在第一个表达式之上选择第二个表达式的原因是,它不必以相同的方式处理溢出,并且对此类问题更具弹性。
事实上,如果你想一下,你可以拥有的最大的第二个值是你的数据类型的最大合法值,所以这种表达式:
X + (Y-X)

... 假设X和Y都是相同的数据类型,至多可以是该数据类型的最大值。基本上,它根本不需要处理溢出问题。

关于algorithm - 找到中间点的最佳方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36228869/

10-10 21:29