【java编程的逻辑】原码 补码 反码以及位运算符

假如我们要把1、2、-127的原码补码反码表示出来

原码反码补码
对于任意的一个数字原码就是转化成为二进制,最高位为符号为,正数为0,负数为1对于正数来说,反码就是其本身;对于负数来说,反码就是除开符号位之后,全部取反对于正数来说,补码就是其本身;对于负数来说,补码就是在反码的基础之上加一
+00000 000000000 00000000 0000
-01000 000001111 11110000 0000
10000 000010000 00010000 0001
-11000 000011111 11101111 1111
1270111 11110111 11110111 1111
-1271111 11111000 00001000 0001
-1281000 0000

在这里插入图片描述

  • 而数字在计算机里面是以补码的形式存在的,为什么要这么做呢?

如果用原码表示的话,范围是(-127,+127),其中+0和-0的码是不一样的
如果用补码表示的话,范围就变成了(-128,+127),这样就可以多表示一个数字,而且+0和-0的码是一样的

  • 如果给定一个负数的二进制表示,想要知道他的十进制的值(1001 0010)

首先我们把1001 0010先取反,得到0110 1101,然后+1,得到 0110 1110,
他的十进制值为110,所以1001 0010的原值就是-110

  • 可能你也会觉得很奇怪,为什么我们将一个原码表示为补码的时候是通过取反再+1,将补码返回的时候为什么还是取反+1,不是应该先-1再取反吗?

在计算机内部,计算机只能运行加法运算,而补码的一个良好的特性就是,对于负数的补码做补码运算的时候,就可以得到其对应于正数的原码
也正是因为这个特性:能让计算机进行减法的操作,其实在计算机内部还是加法操作,不过是从1-2变成了1+(-2)
如果我们用原码进行操作的话:
在这里插入图片描述
如果我们用补码进行操作:
在这里插入图片描述

  • 为什么正数相加,会产生负数呢?

通过以上的理解,我们可以看出如果相加的数字超过表示的范围的话,就会向最高位进行进位,然后读取的时候就会被判断成为负数了
例如:
127(0111 1111)
+1( 0000 0001)
————————
-128(1000 0000)

  • 位运算符

1)左移:
操作运算符为:<<,向左移动,右边的低位补0,高位的舍弃,将二进制看做整数,左移相当于*2
2) 无符号右移:
操作运算符为:>>>,向右移动,右边的舍弃,左边的补零
3)有符号右移:
操作运算符为:>>,向右移动,右边的舍弃,左边看最高位是什么,是1就补1,是0就补0。将二进制数看作整数,右移一位相当于除以2

  • 二进制数出现0.1f0.1f=0.010000001的情况
    因为二进制数不能精确的表达不是2的倍数的数字,十进制也一样,例如10/3=0.333。但是0.333
    3的的结果却是0.999,那么我们对于一些金钱数字需要特别精确的时候,而java的操作数不精确是常态,我们怎么办呢?
    这里有两种方法:(一)先将小数转化成为整数,整数肯定是2的倍数,计算的结果是绝对正确的,然后我们再将将计算的结果转化成为小数;(二)使用十进制数,再java中是BigDecimal
    这也是我们在定义金钱字段的时候为什么用的是bigdecimal而不是float和double了
  • float和double浮点数在计算机内部的存储格式
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值