在许多算法中,我看到人们使用两种不同的方式来获得中间点。
大多数情况下,我在QuickSort中看过第二种方法。在两个数字之间找到中间的最佳方法是什么?为什么?
答案 0 :(得分:4)
这完全取决于上下文,但我会为案例编号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位值)。
那会发生什么呢?有两个结果:
(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都是相同的数据类型,最多可以是该数据类型的最大。基本上,它根本不需要应对溢出。
答案 1 :(得分:2)
使用第二种方法,以避免在计算过程中出现 int 溢出。 想象一下,你只使用了1字节无符号整数,如果值达到256就会发生溢出。想象一下,我们有低= 100和高= 200。见计算:
1. (lo + hi) / 2 = (100 + 200) / 2 = 300 / 2; // 300 > 256, int overflow
2. lo + (hi - lo) / 2 = 100 + (200 - 100) / 2 = 150; // no overflow
答案 2 :(得分:1)
没有最好的一个,但它们明显不同。
他们都有自己的优势和劣势。没有胜利者。
答案 3 :(得分:1)
最好的方法取决于你想要完成的事情。第一个显然更快(最好的性能),而第二个用于避免溢出(最好的正确性)。因此,您的问题的答案取决于您对"最佳"。
的定义