正在学习计算机组织与结构,为了写一些底层的算术操作模拟,比如一个二进制补码数的加减乘除,发现这很麻烦,因为不管是什么语言,都只提供了8位、32、64位等部分位数的补码形式,那么怎么实现任意任意位的补码整数呢,由于我们不能利用现有的如Byte、Integer类,所以我们需要一个容器来存储我们自己编写的任意位的补码整数。

数组可以实现,但是数组移位可能比较麻烦,比如如果要实现二进制数的算术右移,必须要移动大部分元素。可以使用链表,虽然获取二进制数某一位的值比较麻烦,但是还是比数组可能更好一点。于是,我们采用基于链表的队列。

/**
* Created by XuTao on 2018/12/1 15:26
* 作用:存储一个n位二进制数,并实现左右移动、取反、求值等操作
/
public class BinaryQueue {
private int size; //二进制的位数
public Node head = new Node(-1); //head只是一个头节点,后面才是二进制数,从左到右,从高位到低位的
public BinaryQueue(int size){ //创建一个size大小的二进制,他被初始化为00000..00
this.size = size;
Node temp =head;
for (int i =0;i<size;i++){
temp .next = new Node(0);
temp = temp.next;
}
} public BinaryQueue(String binary){ //以二进制数创建
this.size = binary.length();
Node temp =head;
for (int i =0;i<size;i++){
temp .next = new Node(binary.charAt(i)-'0');
temp = temp.next;
}
} public void shiftLeft(){ //左移
head.next = head.next.next;
Node temp = head.next;
for (int i=0;i<size;i++){
if (i==size-2) {
temp.next = new Node(0);
break;
}
temp = temp.next;
}
} public void shiftRight(){//右移
Node first = head.next;
head.next = new Node(0);
head.next.next=first; Node temp = head;
for (int i =0;i<size;i++){
temp = temp.next;
}
temp.next =null;
} public void shiftRightArithmetically(){ //算术右移,符号扩展
Node first = head.next;
head.next = new Node(first.value);
head.next.next=first; Node temp = head;
for (int i =0;i<size;i++){
temp = temp.next;
}
temp.next =null;
} public BinaryQueue reverse(){//按引用传递,会改变值
BinaryQueue bq = new BinaryQueue(this.getStr()); // 重新建立一个,不改变原来的二进制
Node temp = bq.head.next;
for (int i =0;i<bq.size;i++){
temp.value = 1-temp.value; //取反,是1,1-1=0;是0:1-0=1
temp = temp.next;
}
return bq;
} public BinaryQueue add(BinaryQueue bq){
//将两个队列中的二进制放入数组中,如果长度不同则需要将短的进行算术扩展,
int len = bq.size>size?bq.size:size;
int [] arr_bq = new int[len];
int [] arr_this = new int[len];
if (bq.size>size){//bq 长,this扩展
String s = bq.getStr();
for (int i =0;i<len;i++){
arr_bq[i] = s.charAt(i)-'0';
}
String s_this = getStr();
for (int j =0 ;j<len;j++){
if (j<len-size){
arr_this[j] = head.next.value;
}
else {
arr_this[j]= s_this.charAt(j-(len-size))-'0';
}
}
}
else { //this 长 ,bq扩展
String s = this.getStr();
for (int i =0;i<len;i++){
arr_this[i] = s.charAt(i)-'0';
}
String s_bq = bq.getStr();
for (int j =0 ;j<len;j++){
if (j<len-size){
arr_bq[j] = bq.head.next.value;
}
else {
arr_bq[j]= s_bq.charAt(j-(len-size))-'0';
}
}
} //相加
int []res = new int[len];
int carry = 0; //上一次加的进位
for (int i = len-1;i>=0;i--){
res[i] = arr_bq[i]+arr_this[i]+carry;
if (res[i]==2){//进位1,本位0
res[i]=0;
carry =1;
}
else if (res[i]==3){//进位1,本位1
res[i]=1;
carry =1;
}
else carry = 0;
}
String str = "";
for (int i =0;i<len;i++){
str+=res[i];
}
return new BinaryQueue(str);
} public BinaryQueue subtract(BinaryQueue bq){ //减法
return this.add(bq.getOppositeNumber());//基于加法
} public BinaryQueue getOppositeNumber(){//取相反数,就是取反加一
String s = "";
for (int i=0;i<size-1;i++){
s+="0";
}
s+="1";
return reverse().add(new BinaryQueue(s));//加一
} public int getInt(){ //获取二进制所代表的补码整数
if (head.next.value==1){
return -Integer.valueOf(getOppositeNumber().getStr(),2);
}
return Integer.valueOf(getStr(),2);
} public void set(int index,int value){ //改变某一位
Node temp = head.next;
for (int i = 0;i<size;i++){
if (i==index)break;
temp = temp.next;
}
temp.value = value;
} public String getStr(){ //获取二进制字符形式
String str ="";
Node temp = head.next;
while (temp!=null){
str+=temp.value;
temp =temp.next;
}
return str;
} public int getLast(){ //获取最低位
Node temp = head;
for (int i = 0;i<size;i++){
temp = temp.next;
}
return temp.value;
} public static void main(String[] args) {
BinaryQueue bq = new BinaryQueue("1000000011");
BinaryQueue bq2 = new BinaryQueue("0000000001");
// System.out.println(bq.add(bq2).getStr());
System.out.println(bq2.getOppositeNumber().getStr());
// System.out.println(bq.getInt());
// System.out.println(bq2.getInt());
// System.out.println(bq.subtract(bq2).getInt());
System.out.println(bq.subtract(bq2).getInt());
} //节点类 }
class Node{
int value;
Node next;
Node (int value){
this.value = value;
} public int getValue() {
return value;
}
}
 
有了我们自己定义的任意的N位补码二进制数,那么我们可以实现一些计算机底层的模拟了,比如布思算法等等。

任意N位二进制的补码实现——队列存放的更多相关文章

  1. 将32位MD5摘要串转换为128位二进制字符串

    将32为MD5摘要串转换为128位二进制字符串: /// <summary> /// 将字符串转成二进制 /// </summary> /// <param name=& ...

  2. (一一五)利用NSKeyedArchiver实现任意对象转为二进制

    [应用背景] 在数据库中存储数据时,如果对象过于复杂,又不必要创建复杂的表,可以直接把整个对象转化为二进制存入数据库字段,然后取出后再还原即可. [实现方法] 在PHP中,使用序列化和反序列化可以实现 ...

  3. python实现IP地址转换为32位二进制

    python实现IP地址转换为32位二进制 #!/usr/bin/env python # -*- coding:utf-8 -*- class IpAddrConverter(object): de ...

  4. 将两个byte型拼接成16位二进制,再转化为十进制

    short s = 0; //一个16位整形变量,初值为 0000 0000 0000 0000 byte b1 = 1; //一个byte的变量,作为转换后的高8位,假设初值为 0000 0001 ...

  5. 32位二进制IP地址与十进制IP地址互相转换

    代码: import java.util.List; import java.util.ArrayList; import java.util.Scanner; public class Transf ...

  6. 将IP地址字符串转为32位二进制

    def str2bin(s): temp = s.split('.') result = '' for i in range(len(temp)): temp[i] = str(bin(int(tem ...

  7. RabbitMQ集群下队列存放消息的问题

    RabbitMQ中队列有两种模式 1.默认 Default 2.镜像 Mirror [类似于mongoDB,从一直在通过主的操作日志来进行同步] *如果将队列定义为镜像模式,那么这个队列也将区分主从, ...

  8. Java的位运算符与二进制转换

    转换: Java整型数据类型有:byte.char.short.int.long.要把它们转换成二进制的原码形式,必须明白他们各占几个字节.,一个字节==8位数 数据类型                ...

  9. 布思算法——Java实现

    前面一篇提到二进制队列实现了 N位二进制的补码,那么我们来实现布思算法. 关于BinaryQueue:https://www.cnblogs.com/XT-xutao/p/10050518.html ...

随机推荐

  1. 【二】Spring Cloud 入门

    官网 版本号: SpringCloud中文网:https://springcloud.cc SpringCloud中文社区:http://springcloud.cn 以下代码就是Maven父子工程, ...

  2. 1.关于Java

    一.Java简介 1.java语言的特性 java语言的重要特性:跨平台: 一次编译,到处运行. 2.java的环境搭建: 1.JRE: java运行环境. JRE = java 虚拟机 + 核心类库 ...

  3. getservbyname和getservbyport

    一.getservbyname函数原型 #include <netdb.h> struct servent *getservbyname(const char *servname, con ...

  4. luogu 2051 中国象棋

    非常好的dp,锻炼思维 f[i][j][k] 前i行有j列放1,k列放2 #include<bits/stdc++.h> #define int long long #define rep ...

  5. Session 快速开始 通过session的attribute通信

    [web.xml] <session-config> <session-timeout>30</session-timeout> <cookie-config ...

  6. dll和lib的关系(转)

    转自http://blog.163.com/zhengjiu_520/blog/static/3559830620093583438464/ 前面有一章说编译与链接的,说得很简略,其实应该放到这一章一 ...

  7. webstorm破解版

    链接:https://www.cnblogs.com/LUA123/p/8452501.html#undefined

  8. git修改历史记录

     1.git stash2.git rebase 45c2d5c --interactive 3.git stash pop4.git add5.git commit --amend      确认编 ...

  9. 使用Excel过滤重复数据

    如题 由于数据太多,没有办法人工过滤,所以借助Excel 我的数据是这样的 需要找出里面重复的数据 首先,选中需要筛选的数据,点击开始 --> 条件格式 --> 突出显示单元格规则 --& ...

  10. java包装类型的坑

    开发中有遇到Long类型比较是否相等,比如Long A和Long B判断是否相等,当时习惯性的直接A==B: 自测的话确实么有问题,但是测试那边测试就有问题,当时郁闷了一下然后换成了A.equals( ...