任意N位二进制的补码实现——队列存放

    正在学习计算机组织与结构,为了写一些底层的算术操作模拟,比如一个二进制补码数的加减乘除,发现这很麻烦,因为不管是什么语言,都只提供了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位补码二进制数,那么我们可以实现一些计算机底层的模拟了,比如布思算法等等。
posted @ 2018-12-01 19:12  Edwin_Xu  阅读(954)  评论(0编辑  收藏  举报