50-数据结构【原码、反码和补码】计算机数表示方法

MessageDigest md5 = MessageDigest.getInstance("MD5");
String pwd = "pass123";
md5.update(pwd.getBytes());
byte[] result = md5.digest();

先看上面一段简单代码,是MD5的加密,把字符串pwd加密后得到类型为byte[]的密文。

那么我们怎么识别,或者直观的理解这个byte[]呢?

这样的例子举不胜举,例如IO的读写,消息的传输,都是以byte[]的方式传输,可以这样讲:目前绝大多数计算机(包括网路设备)之间数据的传输都是byte[]类型。

也就是说,我们能之间操作的最小单元是byte,即字节(8bit)。

为什么呢?我们都知道,计算机Bus传输是8位的,比如网线、双绞线、总线等。这里特别注意:32位和64位是计算机一次能处理的二进制数是2^32和2^64,指的是cpu处理能力,不要混淆。

接下来我们一起学习它的原理。

byte[]其实是一组连续内存地址单元(每个地址8bit)组成的。每个byte表示由8位0和1组成的二进制,范围是-128~127。

扩充知识,内存的寻址算法是:首地址a0+n,其中n表示该类型所表示的字节个数。
其中:byte、boolean的字节个数是1;short、char的字节个数是2;int、float的字节个数是4;
long、double的字节个数是8;(1个字节是8个bit)

那么,byte的范围为什么是-128~127,而不是0~255或者-127~127呢?

以下1、2、3摘自链接:https://blog.csdn.net/weixin_38357164/article/details/87912475

 1:我们知道计算机底层都是加法计数器运算,不能计算减法,但是我们生活中还必须有负数,有减法,这样符合人类数学思维习惯。

 2:我们还知道一个byte字节占八位,也就是八位1和0组成的二进制数串,这个数串最小是00000000,最大是11111111,也就是表示了0-255的范围,那么问题来了。这个范围都是正的啊,没有负数,没有负数就没有减法,怎么办?

3:其实我们正好反过来解决了这个问题,计算机底层都是要将一个byte存储的负数转换成0-255范围的正数来计数的,但是按照人类的习惯,要直接在写代码的时候就有负数,有减法才能符合人类的思维习惯,那么怎么将负数和减法在计算机的世界里表现出来呢。这时候补码就诞生了。

计算机中的符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,是计算机中对数字的二进制定点表示方法。符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。下面依次介绍并给出相互的转换关系:

原码:

简单直观;例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011。但参加运算可能出错。例如数学上,1+(-1)=0,而在二进制中,00000001+10000001=10000010,换算成十进制为-2,显然出错了。

反码:

反码通常是用来由原码求补码或者由补码求原码的过渡码。反码跟原码是正数时,一样;负数时,反码就是原码符号位除外,其他位按位取反。

补码:

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

1、一个负整数(或原码)与其补数(或补码)相加,和为模。
2、对一个整数的补码再求补码,等于该整数自身。
3、补码的正零与负零表示方法相同。
总之,正整数的补码是其二进制表示,与原码相同。求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。
 
即正整数的原码反码补码一样;负整数的反码是除了原码符号位其他位全部取反,补码是反码加一。

 注:附图一张,-128的补码好像有点问题,后面再补充

____________________________特此,勉励____________________________
本文作者cheng2839
本文链接https://www.cnblogs.com/cheng2839
关于博主:评论和私信会在第一时间回复。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
原文地址:https://www.cnblogs.com/cheng2839/p/14814594.html