<pre name="code" class="java">package test;
/**
* @Classname: Binary
* @Description: TODO 二进制
* @Author: chenn_xu@sina.cn
* @Date: 2015年10月22日 上午11:11:18
* @Version:V1.0
*
* 本篇代码阐述:二进制基本原理、反码、补码、及其计算机如何运算
* 基本原理:
* 在java中的int数据类型占4个字节
* 计算机里每个字节=8位
* 从右到左,由低位到高位,逢2进1;最高位为符号位(0代表正数,1代表负数);java没有无符号数;
* int i = -2 ;原码:10000000000000000000000000000010
* int i = -1 ;原码:10000000000000000000000000000001
* int i = 1 ;原码:00000000000000000000000000000001
* int i = 2 ;原码:00000000000000000000000000000010
* int i = 3 ;原码:00000000000000000000000000000011
* int i = 4 ;原码:00000000000000000000000000000100
* Binary.getIntByOriginalCode(code);模拟实现将java中int数据类型的原码转为数值
* Binary.getOriginalCode(number);模拟实现通过java中int数据获取的对应的原码
* 反码:
* 正数的反码:等于原码;
* 0的反码:等于原码;
* 负数的反码:最高位符号位不变,其他位去反;
* Binary.getReversalByOriginalCode(code);模拟实现通过java中int数据获取的对应的反码
* 补码:
* 正数的补码:等于原码;
* 0的反码:等于原码;
* 负数的反码:等于反码+1
* Binary.getComplementByOriginalCode(code);模拟实现通过java中int数据获取的对应的补码
* 计算机计算:
* 都是通过反码进行计算的(ps:结果也是补码)
* 如:2-1=1;(计算机进行加减时都是通过加的方式)2+(-1)
* 2的原码:00000000000000000000000000000010
* 2的补码:00000000000000000000000000000010
* -1的原码:10000000000000000000000000000001
* -1的补码:11111111111111111111111111111111
*
* 00000000000000000000000000000010
* + 11111111111111111111111111111111
* ——————————————————————————————————————
* = 00000000000000000000000000000001(这也是补码)原码:00000000000000000000000000000001 = (数值)1(正数的补码是原码,so不变)
* 二进制加法:1+1
* 原码:
* 00000000000000000000000000000001
* 00000000000000000000000000000001
* 补码:
* 00000000000000000000000000000001
* 00000000000000000000000000000001
* ________________________________
* 00000000000000000000000000000010 = 2
*
* 二进制减法:1-2
* 原码:
* 00000000000000000000000000000001
* 10000000000000000000000000000010
* 补码:
* 00000000000000000000000000000001
* 11111111111111111111111111111101
* ————————————————————————————————
* 11111111111111111111111111111110
* 原码:
* 10000000000000000000000000000001 - -1
*
* 二进制乘法:5*7
* 00000000000000000000000000000101
* 00000000000000000000000000000111
* ————————————————————————————————
* 00000000000000000000000000000101
* 0000000000000000000000000000101
* 000000000000000000000000000101
* ————————————————————————————————
* 00000000000000000000000000100011 = 2的5次方+2的1次方+1 = 32 +2 +1 =35
*
* 二进制除法:35/5
* 00000000000000000000000000100011
* 00000000000000000000000000000101
*
* 111 = 2的2次方 + 2的1次方+ 1 = 4+2+1 = 7
* ____________________________
* 101 | 100011
* 101
* ____________________________
* 1111
* 101
* ____________________________
* 101
* 101
* ____________________________
* 0
* java 位运算符:
* 取反(~):不管正数还是负数、符号位,统统反向 ps:取反后也是补码
* 按位与(&):两个为1才为1,否则为0 (两原码按位比较)
* 按位或(|):1个为1为1,否则为0 (同理)
* 异或(^):两个不同才取1,否则为0
* 算数左移(<<):<span style="font-family: Arial, Helvetica, sans-serif;">符号位不变,低位补零</span>
* 算数右移(>>):<span style="font-family: Arial, Helvetica, sans-serif;">低位溢出,符号不变,并用符号位补溢出来的高位</span>
* 逻辑右移(>>>):低位溢出,高位补零
*/
public class Binary {
public static void main(String[] args) {
try {
System.out.println(getOriginalCode(-8));
System.out.println(-8>>>2);
//转为数值
System.out.println(Binary.getIntByOriginalCode("00111111111111111111111111111111"));
//转为原码
//System.out.println("1:"+Binary.getOriginalCode(1));
//System.out.println("2:"+Binary.getOriginalCode(2));
//System.out.println("3:"+Binary.getOriginalCode(3));
//System.out.println("4:"+Binary.getOriginalCode(4));
//转反码
//System.out.println(Binary.getReversalByOriginalCode("10000000000000000000000001000000"));
//转补码
//System.out.println(Binary.getComplementByOriginalCode("00000000000000000000000001000000"));
} catch (Exception e) {
e.printStackTrace();
}
}
//根据原码获取补码
public static String getComplementByOriginalCode(String code)throws Exception{
if (code==null || code.length()!=32 || getFrequency(code,"1")+getFrequency(code,"0")!=32) {
throw new Exception("非法java>int数据类型二进制原码,请检查字符串!");
}
//正数的补码是等于原码
if (code.substring(0,1).equals("0")) {
return code;
}
//负数的补码:补码的反码加1
String[] $code = getReversalByOriginalCode(code).split("");
for (int i = $code.length-1; i >=1 ; i--) {
if (i == $code.length-1) {
if ($code[i].equals("0")) {
$code[i]="1";
break;
}
$code[i]="0";
continue;
}
if ($code[i].equals("0")) {
$code[i]="1";
break;
}
if (i==1) {
throw new Exception("该二进制长度超出java>int存储范围!");
}
}
StringBuffer complement = new StringBuffer();
for (int i = 1; i < $code.length; i++) {
complement.append($code[i]);
}
return complement.toString();
}
//根据原码获取反码
public static String getReversalByOriginalCode(String code)throws Exception{
if (code==null || code.length()!=32 || getFrequency(code,"1")+getFrequency(code,"0")!=32) {
throw new Exception("非法java>int数据类型二进制原码,请检查字符串!");
}
//正数的反码是等于原码
if (code.substring(0,1).equals("0")) {
return code;
}
//负数的反码:最高位符号位不变
StringBuffer complement = new StringBuffer();
String[] $code = code.split("");
for (int i = 1; i < $code.length; i++) {
if (i==1) {
complement.append("1");
continue;
}
complement.append($code[i].equals("1")?"0":"1");
}
return complement.toString();
}
/**
*
* @Methodname: getOriginalCode
* @Discription: TODO 获取int数据在计算机中的原码
* @param i
* @return 原码
*
*/
public static String getOriginalCode(int number)throws Exception{
String[] code ="00000000000000000000000000000000".split("");
String[] locations = getLocation(Math.abs(number)).split(",");
for (int i = 0; i < locations.length; i++) {
int location = 32-Integer.parseInt(locations[i]);
if (location >= 32) {
break;
}
code[location+1] = "1";
}
if (number<0) {
code[1]= "1";
}
StringBuffer originalCode = new StringBuffer();
for (int i = 1; i < code.length; i++) {
originalCode.append(code[i]);
}
return originalCode.toString();
}
private static String getLocation(int number)throws Exception{
if (number == 0) {
return "-1";
}
for (int i = 1; i < 32; i++) {
if (Math.pow(2, i-1)==number) {
return String.valueOf(i);
}
if (Math.pow(2, i-1)<number && Math.pow(2, i)>number) {
return String.valueOf(i)+","+getLocation(number-(int)Math.pow(2, i-1));
}
}
throw new Exception("超出java>int数据类型二进制原码二进制存储范围!");
}
/**
*
* @Methodname: getIntByOriginalCode
* @Discription: TODO 根据原码获取数值
* @param code 原码
* @return 数值
* @throws Exception
* remark:
* 求原码公式:累加2的(位数-1)次方, ps:从低位开始算位数
*
*/
public static int getIntByOriginalCode(String code)throws Exception{
if (code==null || code.length()!=32 || getFrequency(code,"1")+getFrequency(code,"0")!=32) {
throw new Exception("非法二进制原码,请检查字符串!");
}
int _int = 0;//结果
int index = 0;//位置
while ((index=code.indexOf("1",index+1))!=-1) {
_int += Math.pow(2,32-index-1);
}
return code.substring(0,1).equals("1")?0-_int:_int;
}
/**
*
* @Methodname: getFrequency
* @Discription: TODO 获得特定字符串在另外字符串中出现的频率
* @param base 字符串
* @param str 特定字符串
* @return 出现的次数
*
*/
private static int getFrequency(String base,String str){
int fromIndex = -2;
int frequency = 0;
while ((fromIndex=base.indexOf(str, fromIndex==-2?0:fromIndex+1))!=-1) {
frequency++;
}
return frequency;
}
}
public static void main(String[] args) {
/**
* 非位运算
* (所有位取返)
*/
//
// 1111 1111 1111 1111 1111 1111 1111 1110
// 0000 0000 0000 0000 0000 0000 0000 0001 结果:1
System.out.println(~-2);
/**
* 异或运算
* (相同则结果为0,不同则结果为1)
*/
// 1111 1111 1111 1111 1111 1111 1111 1101
// 1111 1111 1111 1111 1111 1111 1111 1110
// 0000 0000 0000 0000 0000 0000 0000 0011 结果:3
System.out.println(-3^-2);
/**
* 或运算
* (两个位只要有一个为1,那么结果就是1,否则就为0)
*/
// 1111 1111 1111 1111 1111 1111 1111 1101
// 1111 1111 1111 1111 1111 1111 1111 1110
// 1111 1111 1111 1111 1111 1111 1111 1111
// 结果解析
// 1111 1111 1111 1111 1111 1111 1111 1110
// 1000 0000 0000 0000 0000 0000 0000 0001 结果:-1
System.out.println(-3|-2);
/**
* 与运算
* (两个位都为1,结果才为1,否则结果为0)
*/
// 1111 1111 1111 1111 1111 1111 1111 1101
// 1111 1111 1111 1111 1111 1111 1111 1110
// 1111 1111 1111 1111 1111 1111 1111 1100
// 结果解析
// 1111 1111 1111 1111 1111 1111 1111 1011
// 1000 0000 0000 0000 0000 0000 0000 0100 结果:-4
System.out.println(-3&-2);
/**
* 左位移运算
*/
// 1111 1111 1111 1111 1111 1111 1111 1101
// 1111 1111 1111 1111 1111 1111 1111 1010
// 结果解析
// 1111 1111 1111 1111 1111 1111 1111 1001
// 1000 0000 0000 0000 0000 0000 0000 0110 结果:-6
System.out.println(-3<<1);
/**
* 右移位运算
*/
// 1111 1111 1111 1111 1111 1111 1111 1101
// 1111 1111 1111 1111 1111 1111 1111 1110
// 结果解析
// 1111 1111 1111 1111 1111 1111 1111 1101
// 1000 0000 0000 0000 0000 0000 0000 0010 结果:-2
System.out.println(-3>>1);
/**
* 无符号右移位运算
*/
// 1111 1111 1111 1111 1111 1111 1111 1101
// 0111 1111 1111 1111 1111 1111 1111 1110
// 0111 1111 1111 1111 1111 1111 1111 1110
System.out.println(-3>>>1);
System.out.println(Integer.toBinaryString(2147483646));
}