二进制(十六进制)的总结:

二进制表示有点难度,所以我专门对这一知识点进行总结,全当做是复习吧!
首先:什么是二进制?
二进制和十进制一样,是一种计数的规则,十进制是逢十进一
那么顾名思义,二进制就是逢二进一了,依次类推,N进制就是逢N进一就是了,不过我们用的多的也就是:
二进制,十进制,十六进制

##为什么要用二进制;因为二进制只有0和1,而计算机是由逻辑电路组成,逻辑电路就两个状态,通电和不通电,所以正好用
0和1来表示两种状态,所以使用二进制是计算机硬件成本最优的选择!
而且二进制也正好符合计数的规则,而只要是能计数,都可以实现任何数学运算

##二进制主要有哪些应用呢:补码,16进制,文字编码

科普!!::
这里稍微说一下:其实我们在电脑上看到的那些数都不是二进制,而是我们知道的十进制,可电脑并不认识十进制,而且电脑都是底层都是通过
二进制来进行数据处理的(不管什么数据),所以计算机并不认识十进制,更准确的来说计算机连二进制也不认识,因为计算机只是认识通电和不通电,
也就是电路的开和关.换句话说也就是电流的高低起伏的变化.
那么计算机又是如何处理二进制的呢,其实很简单,二进制只是认为的规定,让计算机电路通了记做"1",断了记做"0",所以这样计算机永远就只有两种
状态,而不需要考虑说还需要其他状态,生产成本降低了.
在我们学习的java里面,输出的都是十进制,其实在只是我们看到的是十进制,内部可并不是这样子的,java一直都是在用二进制进行计算,只不过我们
看不到而已.那么这个魔术手段是什么呢:首先当我们把数据输进电脑,java会自动调用 parseInt() 方法,来把我们输入的十进制数据转换成二进制,
然后用这些二进制数据进行着数学计算,最后要输出结果的时候,java又会调用| toString() |方法来把二进制数据转换成十进制,这一系列转换我们可以debug跟踪到.

先来说一下二进制的技术规则吧:
首先二进制只用两个数来计数:1 | 0
也就是只要有一位上等于2了就要向前进一,和十进制一样,简单来说就是"逢二进一"

十进制也好,二进制也好,都有权这一说法,权表示的是在本位置上的数字是多少就是代表这个数字乘以权,举个栗子:
拿我们最熟悉十进制来说,个位上的5就是代表5x1=5,十位上的5就是代表5x10=50,百位上的5就是代表5x100=500,依次类推;
即:…|1000|100|10|1------这里的规律是…|103|102|101|100
所以从十进制上有规律了,那么二进制就好找规律了,十进制的权是10n,那么二进制每一位的权就是2n了
即二进制的权就是…|256|128|64|32|16|8|4|2|1

下面来总结一下二进制的转换把!

##十进制转二进制:(其实这个很简单)
第一步找到十进制数在二进制的权的区间,例如十进制的134在二进制的256和128之间
第二步用134依次减二进制的权,如果减完大于或等于零,则说明能减,就在二进制的权下面标一个1,然后继续
用余数去依次往下减,和上面的一样,小于权的在权下面标0,一直减到权的最后一位,二进制这就是权下面的0,1组合
例如:134的二进制就是10000110.

134
256 128 64 32 16 8 4 2 1
1 0 0 0 0 1 1 0
134 6 6 6 6 6 2 0 0

##二进制转十进制:
二进制转十进制其实和十进制转二进制差不多,就是分别在二进制的每一位下面把权标上,然后用每一位的数乘以权
最后把所有的乘积进行加法运算;

1 0 0 0 0 1 1 0
128 64 32 16 8 4 2 1 得到:2+4+128=134

好了到这里就学会了二进制和十进制的相互转化;
接下来回顾一下补码的知识:
java在toString 和 parseInt
中封装了补码的算法,在数据输入和输出的时候自动调用,自动化支持补码

因为计算机中是不认识负数的,
java也是一样为什么我们能看到输出负数呢,那是因为负号都是java经过补码计算
然后作为一个字符添加上去的.
补码简单的理解来说就是计算机利用整数来表示负数,到头来还是节省了硬件成本.
补码的规律:

                               [0]                                                                           
                               0000  
                      [-1] 1111    0001 [1] 
                   [-2] 1110         0010 [2]
                 [-3] 1101             0011 [3]
                [-4] 1100                0100 [4]
                 [-5] 1011             0101 [5]
                   [-6] 1010          0110 [6]
                      [-7] 1001    0111 [7](max)
                               1000
                               [-8](min)
                      {上图就为4位补码绘图一}

所以从上图就能看出来,4位补码中最大值为0111(7),最小值为1000(-8),-1为:1111
也可以看出来,正数都是以0开头的,负数都是以1开头的

补码就相当于一个时钟的圆盘,为了更形象的说明,用四位二进制来说明:
正数 ## 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111

负数 ## 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111

所以这里第一行代表的是正数:0,1,2,3,4,5,6,7
第二行代表的负数:-8 -7 -6 -5 -4 -3 -2 -1
观察上面的规律就能发现:正数的最小值是0000,最大值是0111
负数的最小值是1000,最大值是1111 -1的二进制是1111
所以这4位的最大值是0111,最小值是1000;
上面的栗子是4位2进制,一个字节代表8位,一个int类型占2个字节,即16位;
所以用int的举例子的话,int的最大值为:01111111 11111111 11111111 11111111
最小值为:10000000 00000000 00000000 00000000
-1为:11111111 11111111 11111111 11111111

补码的一些规律:
1##取反对称规律(这是不符合数学计数规则的,只适用于二进制)(不包含max和min)
公式: ~n+1=-n; " ~ "是取反符号,代表0变1,1变0,例如~1010=0101;
注意,取反对称规律是补码规定的基础上存在的规律,补码并不是由这个公式得到的.
正数的补码和原码相同,即就是自身.
负数的补码是自身取反加1,例如:-3的补码就是~1101+1=0010+1=0011=3;

$$:注意:取反对称并不是说是来求补码的,因为这个公式只是表示上面图一那样的规律,
例如:对1(0001)取反加1就会得到-1(1111),但1的补码是本身,并不是-1,所以在对补码
的理解和取反对称规律不能会为一谈.

由于有了上面的认知,我们就能总结出如果想要求一个数n的二进制,可以通过他的相反数来求得;
比如我想求-4的二进制,那是多少呢?
-4就是-4的相反数4取反加1;----> ~0100+1=1011+1=1100;即-4的二进制为1100
so easy吧!!

这里科普一下!!:(这是计算机的计数规则)
二进制数的原码,反码,及补码的表示.
1.机器数与真值
机器数:数在机器中的编码表示;
真值:一半书写表示的数;
符号位:代表正 负号;
因为在计算机运算中,数值和符号完全数字化,采用把各种符号位和数字一起编码的方法

a–原码表示

    在机器数中,符号位用0代表正数,用1代表负数,数值用二进制表示.
    例如:
    [X]原=符号位+绝对值
      若X=+1100110     则   [X]原=01100110
        X=-1100110     则   [X]原=11100110

 b--反码表示
    机器数的反码可由原码得到,
    正数:[X]反=[X]原
    负数:[X]反=对[X]原出符号位外各位取反
    栗子:
      若 X=+1100110    则[X]反=01100110
         X=-1100110    则[X]反=10011001

  c--补码表示
     机器数的补码也可以由原码得到.(其实可以理解为是通过反码得到)
     正数:[X]补=[X]原
     负数:[X]补=[X]反+1
     栗子:
      若 X=+1100110    则[X]补=[X]原=01100110
      若 X=-1100110    则[X]补=[X]反+1=10011001+1=10011010

##溢出规律:
n+(max+1)*2=n
n-(max+1)*2=n
为什么要了解溢出呢?不是因为要利用溢出的结果,因为不管什么溢出的结果都是没有任何意义的,
我们之所以要去了解它,是因为只有了解它才能更好的避免工作中发生溢出的情况,溢出不是随机的,
它是一个确定的结果

java中的最小单位是int,因为byte和short和char都是用int来存放数据,可以用Integer的静态方法toBinaryString()实验
该方法可以输出一个int类型的二进制数,Long也有toBinaryString()方法,其输出就是输出long类型的二进制数.当然这里int类型也行

二进制的运算:
运算符: >>> >> << ~ & |
— >>>:无符号右移运算,逻辑右移
— >> :右移运算,数学右移(带符号右移)
— << :左移运算
— ~ :取反运算
— & :and 与运算
— | :or 或运算

经典面试题:
优化算法:n*8
答案:n<<3
注意: 后面乘数必须是2的整数倍数次幂才能优化,否则不行

二进制的移位运算:就是在二进制的基础上对数字进行平移,在移位计算中,byte,short,char移位前都会自动转化成int类型;
规定:int类型进行移位的时候,实际移动的次数是移动的次数和32的余数.也就是说移动33次和移动一次是一样的;
long类型…64的余数.

接下来都是用int类型来举例子:

a—左移运算 <<

运算规则:把数字的二进制形式所有的数字都向左移动对应的位数,高位移除舍弃,低位空位用0补齐;
例如:  3 << 2
    3-->二进制形式:00000000 00000000 00000000 00000011
    向左移动2位得: 00000000 00000000 00000000 00001100   -->12=3*2^2
    所以可以得到,在没有溢出的情况下,正数负数,左移移位相当于乘以2的1次方,左移n次相当于乘以2的n次方.
    即:x << y --> x*2^y
    这里就可以解释上面的经典面试题了:n*8==n << 3;   (是不是突然发现 << 很简单啊)

b–数学右移 >>

运算规则:把数字的二进制形式所有的数字都向右移动对应的位数,低位移除(舍弃).高位空位补符号位,正数补0,负数补1,
由于要保证正数移位后仍然是正数,负数移位后仍然是负数.
注意!:这里的高位补符号位不是光之最高位,而是指向右移动了几次,就要补几个符号位.
例如: -11 >> 2
      -11-->二进制形式:11111111 11111111 11111111 11110101  
      向右移动2位得:   11111111 11111111 11111111 11111101  --> -3
      右移一位相当于除以2的一次方,右移n位,相当于除以2的n次方,然后向下取整所得.
      即x >> y --> Math.floor(x/2^y)
      这里如果不能整除,则是向下取整,向下取整的意思就是如果是小数,总会向最小的那个小数取整,举个栗子:
      -11 >> 3 --> Math.floor(-11/8)=Math.floor(-1.375)=-2
      11 >> 3  --> Math.floor(11/8)=Math.floor(1.375)=1

c–无符号右移 >>>

运算规则:把数字的二进制形式所有的数字都向右移动对应的位数,低位移除(舍弃),高位的空位补0,所以对于正数来说是一样的
对于负数来说是不一样的.其他结构和>>相同.

二进制的逻辑运算:

a–and & 逻辑与运算

运算规则:将两个操作数按位对齐,每个位置进行乘法运算,称为与运算
与运算可以对数据进行拆分.
int n=100;
00000000 00000000 00000000 01100100
int m=15;(2的x次幂-1代表要截取从n的尾部截取x位数)
00000000 00000000 00000000 00001111
所以int i=n & m;-->
00000000 00000000 00000000 00000100
即从i的尾部截取4位:0100;
与运算的用途:用于截取一个数的特定数位
一个经典案例:将一个正数int拆分为4个byte

b–or | 逻辑或运算

运算规则:将两个数对齐,上下位置数字进行逻辑加法,可用于将byte合并为int
逻辑加法: 0|0=0 , 0|1=1, 1|0=1, 1|1=1
或运算用途:用于对数据进行拼接;
所以,如果要拼接,那么在拼接的位置上,有一方必须为零,因为如果双方都为1,那么结果还是1,
这样就会覆盖掉一方的信息,对拼接有影响.
例如:
              a= 00000000 00000000 10110101 00000000
              b= 00000000 00000000 00000000 11010010
于是     a | b = 00000000 00000000 10110101 11010010

##十六进制:
16进制其实就是2进制的缩写,其产生的原因也是为了降低硬件生产成本;能更好的计数,计算机内部只用2进制进行计算.
十六进制的表达方式:(注意这里字母大写小写都行)

                2进制     16进制
                0000        0
                0001        1
                0010        2
                0011        3
                0100        4
                0101        5
                0110        6
                0111        7
                1000        8
                1001        9
                1010        a
                1011        b
                1100        c
                1101        d
                1110        e
                1111        f
            {16进制分别对应的二进制码}

其中16进制数是以0x开头;
-1用16进制的表示:
1111 1111 1111 1111 1111 1111 1111 1111
0x f f f f f f f f -->0xffffffff
最大值max用16进制表示:
0111 1111 1111 1111 1111 1111 1111 1111
0x 7 f f f f f f f -->0x7fffffff
最小值min用16进制表示:
1000 0000 0000 0000 0000 0000 0000 0000
0x 8 0 0 0 0 0 0 0 -->0x80000000

综合练习:
一:对颜色进行截取
对颜色RGB进行截取:-----------------下面给出两种表达方式--------->>>
颜色的16进制表示: color=0x00b0d8f8
R(red) : 248 G(gree): 216 B(blue): 176
(RGB的数是用十进制表示的)
第一步:0xe8b888 的二进制形式–> 0000 0000 1011 0000 1101 1000 1111 1000
第二步:color & 255 -->就可以把最后八位截取下来,即是代表R
第三步:把color向右移位,这里可以用 >>,也可以用>>>,因为正数这两个没有影响,高位都是补0
这里向右移动8位,因为把R截取完,然后准备截取G. --> color >>= 8;
第四步:color & 255 -->可取出G 然后 color >>= 8;
最后 :color & 255 -->可取出B

 二:对颜色进行拼接
 把颜色按照相反的顺序依次拼接起来,插入顺序: B-->G-->R
 第一步:把B的二进制做左移8位的操作,即:color=B << 8.
 第二步:把B的左移结果和G的二进制做或运算 color |= G 也就是拼接.并且color <<= 8;
 第三步:把第二步的操作结果和R的二进制做或运算 color |= R 也是进行拼接操作.
 最后输出的就是上面的.只不过IDE输出的时候会自动在内部把二进制转化为十进制
 输出的时候显示的是十进制数字,如果用Integer.toBinaryString()则可以看到输出的二进制
 注意:如果前面有0,则IDE会直接把0去掉.

在互联网的数据传输的时候,都是将数据拆分为byte然后进行传输,所以要对数据进行编码和解码.
而编码和解码都是对二进制的编解码操作.

文字的编码:
将char数据拆分为byte数据,称为文字的编码,将byte数据合并为char类型数据称为文字的解码;
UTF-16BE
将char拆成两半,支持65535个字符,但是英文字符只占一个字节,即1byte,所以英文就会浪费一半的空间.

于是出现了UTF-8编码,又称为万国码.
UTF-8:支持10万字+ 的字符,是变长编码,1-4个字节编码:
英文1字节节省空间,中文正好占位在3个字节中间,但是Unicode让中文实际占用4个字节位置(只是给中文字符加了特殊标志)
UTF-8:是国际最优编码.

GBK:中国标准
也是变长编码 1~2个字节,英文1个字节,中文2个一共20000+ 字符
GBK:是中国本地化最优编码.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值