Take a look at GW

【算法】详解进制

目录结构:

contents structure [+]

1,为什么计算机代码需要用2进制表示

  大家都知道我们熟练的机制是十进制,也就是(0到9),逢10进1。如果要让电脑使用十进制,首先,应该让电脑能够识别出10个数字。通常的考虑是,通过元器件中电压的高低水平来分别标识10个数字。假如最高电压为10V,那么每个数字标识的就是1V,这种情况造成的后果就是每个数字的电压很容易收到外界电压干扰。除了这种问题,还有一个更大的问题,就是如果要在硬件上识别这10中状态,其电路结构将非常复杂。

   由于二进制数只有2个数码,电路就很简单了,因为只有两种稳定状态下的元件。二进制主要有以下优点:

  *运算规则简单

  *适合逻辑运算

  *易进行转化

  *抗干扰能力强

2,原码、反码、补码的关系

  首先需要知道,电脑的编码都是补码,正数的原码、反码和补码都是一样的,负数的补码的是原码按位取反得到反码后再加1。

  比如:

    1的原码为:00000001

    1的反码为:00000001

    1的补码为:00000001

    -1的原码为:10000001

    -1的反码为:11111110

    -1的补码为:11111111

  2.1为什么需要反码、补码

    计算机中没有减法、乘法、除法运行,都是通过加法来实现的。比如通过1+(-1)来实现减法。

    不使用反码和补码:

      3-2=3+(-2)=0000 0011+1000 0010=1000 0101=-5

      显然结果不正确。

    使用反码不使用补码:

      3-2=3+(-2)=0000 0011+1111 1101=1 0000 0000=0

      这里得到结果的二进制有9位,如果我们只是考虑8位,那么结果取后面8个0,转化位十进制也就是0。

    使用补码

      3-2=3+(-2)=0000 0011+1111 1110=0 0000 0001=1

      使用补码就能得到正确的答案

2.2原码、反码、补码之间的关系

计算机中最终计算的都是机器码,对于数字来说也就是下面的补码。正数的原码、反码、补码相同,负数的反码是原码按位取反(符号位不变),负数的补码是反码加1(符号位不变)。原码的计算规则是,首先得到这个数的绝对值的二进制,然后再判断这个数是正数还是负数,如果这个数是正数把最高位赋值为0,如果是负数就把最高位赋值为1。

比如:-1

原码:1000 0001(-1绝对值的二进制为0000 0001,然后由于-1是负数,所以把最高位赋值为1.)

反码:1111 1110

补码:1111 1111

所以计算机中存储-1的最终代码为1111 1111

 

比如:-128

原码:1000 0000(首先-128的二进制是1000 0000,然后-128是一个负数所以把最高位赋值为1,恰好最高位已经是1,所以-128原码就是1000 0000)

反码:1111 1111

补码:1000 0000

所以在计算机中存储-128的最终代码为1000 0000

还有需要注意的就是,如果我们在赋值的时候直接给变量赋二进制,那么这里是赋值的就是补码,也就是机器码。

3,进制的转化

  3.1 十进制和二进制的相互转化

  十进制转二进制规则:整数部分除2取余,倒序排列。小数部分乘2取整,正序排列。

  例如

    某个数字:15.4

    整数部分为:0000 1111。

    小数部分为:

      0.4*2=0.8 取整为0 余下 0.8

      0.8*2=1.6 取整为1 余下 0.6

      0.6*2=1.2 取整为1 余下 0.2

      ...........

    保留两位小数,则是01

    于是15.4的二进制为0000 1111.01,可通过在线二进制转化器进行验证

  二进制转十进制的规则:按权展开,以此相加。

  例如

    某个二进制:0000 1111

    转化为十进制:1*2^(0)+1*2^(1)+1*2^(2)+1*2^(3)+0*2^(4)+0*2^(5)+0*2^(6)+0*2^(7)=15

  3.2 八进制和二进制的相互转化

    八进制转二进制规则:“一位转三位”;

    二进制转八进制规则:“三位合一位”;

  3.3 十六进制和二进制的相互转化

    十六进制转二进制规则:“一位转四位”;

    二进制转十六进制规则:“四位合一位”;

4,一个字节能够表示的数据范围

  一个字节有8位,最高位为0表示正数,最高为1表示负数。

  那么:

    一个字节的正数范围“0000 0000 ”-“0111 1111”,转化为十进制就是“0”-“127”。

    一个字节的负数范围“1000 0000”-“1111 1111”,转化为十进制就是“-128”-“-1”。

  所以能够表示的数据范围“-128”-“127”。

5,整型数据溢出

接下来在java中运行如下代码:

public class TestYc{
  public static void main(String [] args){
    byte b=(byte)130;
    System.out.println(b);//-126
  }
}

会输出如下-126,byte存储数据的范围(-128 到 127),显然130超过了127,所以存在数据溢出。

我来计算一下,

byte存储的最大整数为:127,对应的二进制代码为:0111 1111。

当把128赋值给byte的时候,也就是127+1,对应的二进制代码为:0111 1111 + 0000 0001 = 1000 0000,对应的十进制为:-128。

当把129赋值给byte的时候,也就是128+1,对应的二进制代码为:1000 0000 + 0000 0001=1000 0001,对应的十进制为:-127。

当把130赋值给byte的时候,也就是129+1,对应的二进制代码为:1000 0001 + 0000 0001=1000 0010,对应的十进制为:-126。

所以从计算我们看出,数据溢出几就在最大数的二进制加上几。

posted @ 2017-04-17 23:27  HDWK  阅读(1012)  评论(0编辑  收藏  举报