寻找中间点的最佳方式

时间:2016-03-25 22:11:31

标签: algorithm math

在许多算法中,我看到人们使用两种不同的方式来获得中间点。

  1. (LOW + HIGH)/ 2
  2. LOW +(高至低)/ 2
  3. 大多数情况下,我在QuickSort中看过第二种方法。在两个数字之间找到中间的最佳方法是什么?为什么?

4 个答案:

答案 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位值)。

那会发生什么呢?有两个结果:

  1. 它会溢出,这意味着它会从0开始向上计数,这意味着它实际上会以3598 (123456 + 56789) - 65536
  2. 的结果结束
  3. 它会抛出一个异常或类似的东西,导致溢出问题导致程序崩溃。
  4. 如果我们得到第一个结果,则(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)

没有最好的一个,但它们明显不同。

  1. (LOW + HIGH)/ 2会在有符号和无符号情况下添加溢出时导致故障。没有必要成为一个问题,如果你认为它永远不会发生,这是一个非常合理的事情。
  2. LOW +(HIGH-LOW)/ 2如果允许LOW任意为负,仍会导致溢出问题。对于非负输入,它很好。花费额外的操作。
  3. (LOW + HIGH)>>>在Java中可以看到1。对于非负但有符号输入,溢出是非破坏性的。符号位用作加法可以携带的额外位空间,然后移位将无符号结果除以2。如果结果被认为是负面的话根本不起作用,因为通过构造,结果是非负的。对于不是真正需要考虑的数组索引。如果您使用的是无符号索引,则无济于事。
  4. 伪x86 asm中的MOV MID,LOW \ ADD MID,HIGH \ RCR MID,显式使用额外的空间,因此无论如何都适用于所有无符号输入,但不能在大多数语言中使用。
  5. 他们都有自己的优势和劣势。没有胜利者。

答案 3 :(得分:1)

最好的方法取决于你想要完成的事情。第一个显然更快(最好的性能),而第二个用于避免溢出(最好的正确性)。因此,您的问题的答案取决于您对"最佳"。

的定义