Java菜鸟学习笔记--语法篇(四):BitOperator原理与详解
来源:互联网 发布:加权平均数的两种算法 编辑:程序博客网 时间:2024/05/16 06:21
What is the problem?
1.计算机存储数据为什要用补码?
2.按位与,或,异或具体内部怎么运算?
3.这些运算主要用于什么方面?
answer
1.为什么要使用补码
在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.
1.1原码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:
[1111 1111 , 0111 1111]
即
[-127 , 127]
原码是人脑最容易理解和计算的表示方式.
1.2 反码
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.
1.3 补码
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补
对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.
1.4 为何要使用原码, 反码和补码
在开始深入学习前, 我的学习建议是先"死记硬背"上面的原码, 反码和补码的表示方式以及计算方法.
现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:
[+1] = [00000001]原 = [00000001]反 = [00000001]补
所以不需要过多解释. 但是对于负数:
[-1] = [10000001]原 = [11111110]反 = [11111111]补
可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?
首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.
于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:
计算十进制的表达式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.
为了解决原码做减法的问题, 出现了反码:
计算十进制的表达式: 1-1=0
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.
于是补码的出现, 解决了0的符号以及两个编码的问题:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补
-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)
使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].
因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.
而且实际上并不是从10000001到11111111依次表示-1到-127,而是刚好相反的,从10000001到11111111依次表示-127到-1
用补码表示负数时:负数X用2^n - |X|来表示,其中n为机器的字长
当n=8时,[-1]补 = 2^8 - 1 = 11111111, [-127]补 = 2^8 - 127 = 100000001
[-0]补=2^8=00000000在补码表示法中只有一种表示,即00000000
如果要扩展的数是符号数,并且采用补码形式表示,进行符号扩展
求补 求补
[X]补 -------->[-X]补 -------->[X]补
2.位运算过程
2.1 &(与)运算
2.1.1简介:
2.1.1示例.与运算实现判断奇偶型功能
public class BitOperator{public static void main(String[] agrs){//1.不同方法判断一个数的奇偶性boolean a,b;a=(500%2!=0);//用除以2,偶数可以除尽,用着个为依据判断b=(500&1)!=0;//用与运算,System.out.println("500%2!=0 is "+a);System.out.println("500&1!=0 is "+b);/*结果:500%2!=0 is false500&1!=0 is false */}}
2.2 OR(|,或)运算
2.3 XOR(^,抑或)运算
简介:
2.示例.用XOR进行简易加密
public class BitOperator{public static void main(String[] agrs){//1.用XOR进行简易加密//要传送的数字消息long massage=123456;System.out.println("原信息为:"+massage);//规定密钥long key=19920508;System.out.println("加密密钥:"+key);//加密信息long review=key^massage;System.out.println("加密后的信息为:"+review);/*输出:19797052这个为收到的直接信息,加密后信息*///解密信息review=review^key;System.out.println("解密后的信息为:"+review);/*输出:19797052这个为收到的直接信息,加密后信息*/}}
效果:
public class BitOperator{public static void main(String[] agrs){//1.用XOR进行简易加密//要传送的charchar massage='c';System.out.println("原信息为:"+massage);//规定密钥char key='1';System.out.println("加密密钥:"+key);//加密信息char review=(char)(key^massage);System.out.println("加密后的信息为:"+review);//解密信息review=(char)(review^key);System.out.println("解密后的信息为:"+review);}}截图:
2.4 NOT(~,取反)运算
3.移位运算
作者:YangGan出处:http://blog.csdn.net/incyanggan本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名Yanggan(包含链接).
- Java菜鸟学习笔记--语法篇(四):BitOperator原理与详解
- Java菜鸟学习笔记--语法篇(三):运算符概述
- Java菜鸟学习笔记--语法篇(五):位运算实例
- Java菜鸟学习笔记--面向对象篇(四):This指针
- Java菜鸟学习笔记--面向对象篇(四):This指针
- java基础语法学习笔记(四)
- Java菜鸟学习笔记--语法篇(一):用Math.random()实现验证码功能
- Java菜鸟学习笔记--语法篇(二):基本数据的自动/强制转换
- 菜鸟Java 学习笔记
- Erlang 程序设计 学习笔记(四) 二进制型与位语法
- 《深度学习原理与TensorFlow实践》学习笔记(四)
- 编译原理学习笔记---语法
- Java菜鸟学习笔记--配置篇(三):Java API 文档下载与文档注释的使用
- 菜鸟学习笔记之java
- 菜鸟学习java并发笔记
- COM学习笔记(四)IDispatch接口原理与应用
- 操作系统精髓与设计原理学习笔记四:线程
- java语法学习笔记
- 浏谷歌览器对<tbody>标签的css样式解释
- 有史以来最出彩的编程语言名字
- directshow播放器 directshow消息
- java实现的经典递归算法三例
- Jquery 复选框取值,FF和IE8好用,测试有效
- Java菜鸟学习笔记--语法篇(四):BitOperator原理与详解
- css3关于device-width /Viewport
- 选择排序法的几个原则
- 不规则窗口
- 算法入门经典二叉树系列 UVO
- 通过SVN命令提交未在版本控制中的文件和文件夹
- 我的Win32开发抉择,Delphi老将复出
- map容器在解决字符串问题的方便之处
- 搜狗、chrome、猎豹三个浏览器所耗内存对比