Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在Java中(high+;low)/2是错误的,但是(high+;low)>&燃气轮机&燃气轮机;1不是吗?_Java_Bit Manipulation_Bitwise Operators_Binary Search - Fatal编程技术网

为什么在Java中(high+;low)/2是错误的,但是(high+;low)>&燃气轮机&燃气轮机;1不是吗?

为什么在Java中(high+;low)/2是错误的,但是(high+;low)>&燃气轮机&燃气轮机;1不是吗?,java,bit-manipulation,bitwise-operators,binary-search,Java,Bit Manipulation,Bitwise Operators,Binary Search,我知道>修复了溢出:当添加两个大的正长时,可能会以负数结束。有人能解释一下这种按位移位是如何神奇地解决溢出问题的吗?它与>有何不同 我的怀疑:我认为这与Java使用了两个恭维词有关,所以如果我们有额外的空间,溢出值是正确的数字,但因为我们没有,它变成了负数。因此,当你移动并用零划桨时,由于这两个赞美,它神奇地得到了修正。但我可能是错的,有点智慧的人必须加以证实。:) 它用零填充最上面的位,而不是用符号填充它们 int a = 0x40000000; (a + a) / 2 == 0xC00

我知道
>
修复了溢出:当添加两个大的正长时,可能会以负数结束。有人能解释一下这种按位移位是如何神奇地解决溢出问题的吗?它与
>
有何不同



我的怀疑:我认为这与Java使用了两个恭维词有关,所以如果我们有额外的空间,溢出值是正确的数字,但因为我们没有,它变成了负数。因此,当你移动并用零划桨时,由于这两个赞美,它神奇地得到了修正。但我可能是错的,有点智慧的人必须加以证实。:)

它用零填充最上面的位,而不是用符号填充它们

int a = 0x40000000;
(a + a)  /  2 == 0xC0000000;
(a + a) >>> 1 == 0x40000000;
简而言之,
(高+低)>>1
是一种技巧,它使用未使用的符号位执行非负数的正确平均


假设
high
low
都是非负的,我们可以确定最高位(符号位)为零

所以
high
low
实际上都是31位整数

high = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
low  = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
当你把它们加在一起时,它们可能会“溢出”到顶部

high + low =       1000 0000 0000 0000 0000 0000 0000 0000
           =  2147483648 as unsigned 32-bit integer
           = -2147483648 as signed   32-bit integer

(high + low) / 2   = 1100 0000 0000 0000 0000 0000 0000 0000 = -1073741824
(high + low) >>> 1 = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
  • 作为有符号32位整数,它是溢出的,并翻转为负数。因此,
    (高+低)/2
    是错误的,因为
    高+低
    可能是负数

  • 作为无符号32位整数,总和是正确的。所需要的就是把它除以2

当然,Java不支持无符号整数,所以我们最好除以2(作为无符号整数)是逻辑右移
>

在使用无符号整数的语言中(如C和C++),由于输入可以是完整的32位整数,因此它变得更加复杂。一种解决方案是:
low+((高-低)/2)


最后,要列举
>>
>
/
之间的差异:


  • >
    是逻辑右移。它用零填充高位
  • >
    是算术右移。它用原始顶部位的副本填充上部its
  • /
    是分区
数学上:

  • x>>>1
    x
    视为无符号整数并将其除以2。四舍五入
  • x>>1
    x
    视为有符号整数并将其除以二。它朝着负无穷远的方向旋转
  • x/2
    x
    视为有符号整数并将其除以2。它接近零

我建议读一下乔希·布洛赫的《关于高和低的》

“我为JDK编写的二进制搜索版本也包含同样的错误。最近,当它破坏了某人的数据库时,Sun收到了报告 在等待了九年左右之后,我们开始了一项计划。”


我想你指的是?你怎么知道它解决了溢出问题?还有,什么溢出问题?Joshua Bloch告诉我:@JohnPristine:2的补码CPU对有符号和无符号整数执行加法的方式完全相同。。。唯一的区别在于
/2
。所以到那时为止,一切都是正确的。显然,因为有足够的位来表示和,所以有足够的位来表示商,
>>1
就是这样做的。
/2
出错的唯一原因是它试图更正符号,显然
>>1
执行按位右移,这与无符号除以2相同。。。因此,它必须正确工作。我不确定这是否回答了你的问题……我的说法是否正确:“我认为这与Java使用两个赞美词有关,因此如果我们有额外的空间,溢出值是正确的数字,但因为我们没有,它变为负值。所以当你移动并用零划动时,它会神奇地得到修复。”?不确定何时使用>>>以及何时使用>>。我认为在这种情况下,我们选择>>>来修复可能的溢出(符号位溢出)问题。在>>和>>>之间选择的经验法则是什么?
>>
是逻辑右移。它用零填充高位
>
是算术右移。它用原始顶层位的副本填充上层位。从数学上讲,
>1
将数字视为无符号,并除以2进行四舍五入<代码>>>1将数字视为已签名,并向下舍入到负无穷大<代码>/2将数字视为有符号的,并向零舍入。很好,答案永远不会变老。