源码-补码-反码

一道简单的面试题,发现自己的bug

题目

int a = 4;
System.out.println(~a);
int b = -4;
System.out.println(~b);

问:程序输出什么

答案:-5和3

解释

前提:

一个字节有8位,首位为符号位,1为负数,0为正数。如10000001 = -1(十进制)00000001 = 1(十进制)

  • 正数补码 = 原码
  • 负数补码在计算的时候按照以下两条规则:
    负数补码 = 【原码符号位】+【剩余原码从右往左除第一个1外,左边按位取反】

    负数补码 = 【原码符号位】 + 【剩余原码按位取反后+1】
    举个例子
    10000001 的补码 = 111111111
    10000101的补码 = 11111011

针对题目解释

在java中存储的二进制一般为数字补码。因此java在运算的时候是按照补码来计算的。针对运算符~ ,在java运算中就是根据补码取反。
因此我们计算中按照以下顺序来计算

  1. 将数据的原码转为补码
  2. 补码按位取反,此时取反后还是补码,我们需要在计算中转为原码
  3. 将取反后的补码转补码

针对4:

  • 4的二进制为00000100
  • 在java中保存 的补码是00000100
  • 根据运算符~ 按位取反是 11111011
  • 然后显示的时候我们将补码转为原码,在进行一次负数补码运算得到
    10000101 = -5

针对-4:

  • -4的二进制是 10000100
  • 在Java中保存的补码是11111100
  • 根据运算符~ 按位取反是 00000011
  • 然后将补码转为原码,因为补码的符号位为0,因此补码与原码一致为00000011 = 3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值