【问题标题】:Java, will (low + high) >> 1 overflow?Java,(低+高)>> 1会溢出吗?
【发布时间】:2016-03-29 23:31:57
【问题描述】:

我知道>> 用于签名,>>> 用于未签名

没有回答我的问题的类似问题:

Java, will (low + high) >>> 1 overflow?

Safe integer middle value formula

根据第二个链接,他们为什么会得出这样的结论: avg = (low & high) + ((low ^ high) >> 1); 会避免溢出吗?

他们为什么不能直接使用这个:(low + high) >> 1

(这是用于java中的二进制搜索)

【问题讨论】:

    标签: java overflow average bitwise-operators


    【解决方案1】:

    是的,如果总和足够高,(low + high) >> 1 可能会溢出。如您所知,>>> 是无符号的,因此它总是会在最重要的一侧移入0。事实证明这非常重要,以防它溢出。

    使用(low + high) 的诀窍是即使溢出,信息仍会保留。如果它确实溢出,最大可能的数学和仍然是Integer.MAX_VALUE * 2,如果Java 有一个,它仍然可以表示为无符号int。但是,当我们使用无符号右移运算符>>> 除以 2 时,我们可以和视为一个无符号整数。当向右位移1 时,这让我们将总和视为无符号int,“未溢出”int

    如果总和溢出,则在此处使用>> 将不起作用,因为它会溢出为负数,而>> 将移入1,使值保持为负。这会导致错误的平均值计算(2 个正数,其总和溢出将导致负平均值)。

    无论您使用的是>>> 还是>>,都有可能溢出。所以两者都可以溢出。但只有>>> 能很好地处理此案,正确地“不溢出”总和。

    诀窍

    avg = (low & high) + ((low ^ high) >> 1);
    

    是在总和可能溢出时计算平均值的另一种方法。这完全避免了溢出。这将总和分为两部分——“进位”位和“非进位”位。

    使用加法时,转移到下一个更高有效位的位是两个位都设置时 -- low & high。此外,通常这些位必须左移,但我们正在计算 2 个数字的平均值,所以最后我们也会右移。最终结果:这里没有变化。

    未携带的位要么是1(如果位不同),要么是0(如果位相同)——这就是(low ^ high) 的来源(异或)。此外,通常这些位不会移动,但我们正在计算 2 个数字的平均值,所以我们最终也会向右移动。这种转变显示为>> 1&^ 运算符不会溢出,因此 >> 在这里可以正常工作。

    示例:1100 (12) 和 1010 (10) 的平均值

    1100 & 1010 = 1000
    1100 ^ 1010 = 0110, 0110 >> 1 = 0011
    1000 + 0011 = 1011 (11)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-20
      • 2023-01-30
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 2015-11-05
      • 2012-12-01
      相关资源
      最近更新 更多