(a + b)/2 和 a + (b - a)/2

在求两个数的中间数时,我们有三种写法

  1. (a + b)/2
  2. a + (b - a)/2 (推荐)
  3. a + ((b - a) >> 1)

这三种看似相同,其实差别很大。
我们先讨论除的两种情况: /2 和 >>1 的区别。

  1. 正数和负数除2
    9 / 2 = 4
    -9 / 2 = -4
  2. 正数和负数带符号右移1位
    9 >> 1 = 4
    -9 >> 1 = -5

这是由于java中int类型“/2”是向0取整,而“>>1”则是位运算

我们使用5位二进制表示+9 表示为 0 1001 ,第一位0是符号+
我们使用5位二进制表示-9 表示为 1 0111 ,第一位1是符号-
>>:带符号右移。正数右移高位补0,负数右移高位补1。
+9 >> 1 = 0 0100 = 4
-9 >> 1 = 1 1011 = 负的 0 0101 = -5
所以我们使用>>时要注意负数情况

        System.out.println("99/2 = "+(99/2));
        System.out.println("-99/2 = "+(-99/2));
        System.out.println();

        System.out.println("99>>1 = "+(99>>1));
        System.out.println("-99>>1 = "+(-99>>1));
        System.out.println();

        System.out.println("a = 200 , b = 99 时的各种情况");
        System.out.println("(200+99)/2 = "+(200+99)/2);
        System.out.println("((-200)+(-99))/2 = "+((-200)+(-99))/2);
        System.out.println();

        System.out.println("200 + (99-200)/2 = "+(200 + (99-200)/2));
        System.out.println("(-200) + ((-99)-(-200))/2 = "+((-200) + ((-99)-(-200))/2));
        System.out.println();

        System.out.println("200 + ((99-200)>>1) = "+(200 + ((99-200)>>1)));
        System.out.println("(-200) + (((-99)-(-200))>>1) = "+((-200) + (((-99)-(-200))>>1)));

打印:

99/2 = 49
-99/2 = -49

99>>1 = 49
-99>>1 = -50

a = 200 , b = 99 或 a = -200 , b = -99 时的各种情况
(200+99)/2 = 149
((-200)+(-99))/2 = -149

200 + (99-200)/2 = 150
(-200) + ((-99)-(-200))/2 = -150

200 + ((99-200)>>1) = 149
(-200) + (((-99)-(-200))>>1) = -150

可以看出
(200+99)/2 = 299 / 2 = 149
200 + (99-200)/2 = 200 + (-101)/2 = 200 + (-50) = 150
这两者的取整出现了不同,这是由于负数导致的。

a + (b - a) / 2 对比 (a + b) / 2 有两个优势

  1. 避免 a + b 应为数字太大导致越界溢出问题。
  2. 如果a、b表示两个指针,那么a + b在编译中是不被允许的(因为两个指针相加得到的另一个指针可能越界或者内存溢出,并且在逻辑上是没有意义的),如果我们想知道a、b指针之间的中间指针时,就只能使用a + (b - a) / 2 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值