为什么使用low + (high - low) / 2而不使用(high + low) / 2呢?

为什么使用low + (high - low) / 2而不使用(high + low) / 2呢?目的是防止溢出!
为什么这样就防止溢出了呢?看下面的例子。

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
low + (high - low) / 2 = 0100 0000 0000 0000 0000 0000 0000 0000 =  1073741824

作为带符号的32位整数,它是溢出的并且翻转为负。因此(high + low) / 2是错误的,因为high + low的运算结果可能超出当前类型所表示的范围的。

如果作为无符号32位整数运算,总和是正确的。所需要的就是将它除以2。

在Java运算中不支持无符号整数,所以我们一般选择low + (high - low) / 2来防止溢出,但有一种是这样写的low + (high - low) >>> 1,在Java中>>>和>>的区别,则在于无符号和有符号。如果使用>>,会将符号位也参与运算。

(high + low) >> 1 = 1100 0000 0000 0000 0000 0000 0000 0000 = -1073741824

一般来说>>和>>>比除法的/的运行效率高,但是经过编译器的优化,他们效率并不相差多少,工作中尽量风格和同事统一,不要擅自使用位运算,这样有可能会造成阅读困难,而且效率也不能提高多少。
如果文中我的理解有偏差或者错误,请阅读者评论指出,不胜感激。

猜你喜欢

转载自blog.csdn.net/weixin_44556968/article/details/110288725