任意N位二進位制的補碼實現——佇列存放
阿新 • • 發佈:2018-12-01
正在學習計算機組織與結構,為了寫一些底層的算術操作模擬,比如一個二進位制補碼數的加減乘除,發現這很麻煩,因為不管是什麼語言,都只提供了8位、32、64位等部分位數的補碼形式,那麼怎麼實現任意任意位的補碼整數呢,由於我們不能利用現有的如Byte、Integer類,所以我們需要一個容器來儲存我們自己編寫的任意位的補碼整數。
陣列可以實現,但是陣列移位可能比較麻煩,比如如果要實現二進位制數的算術右移,必須要移動大部分元素。可以使用連結串列,雖然獲取二進位制數某一位的值比較麻煩,但是還是比陣列可能更好一點。於是,我們採用基於連結串列的佇列。
2
3 /**
4 * Created by XuTao on 2018/12/1 15:26
5 * 作用:儲存一個n位二進位制數,並實現左右移動,取反等操作(補碼形式)
6 */
7 public class BinaryQueue {
8 private int size;
9 private Node head = new Node(-1); //head只是一個頭節點,後面才是二進位制數,從左到右,從高位到低位的
10 public BinaryQueue(int size){ //建立一個size大小的二進位制,他被初始化為00...00
11 this.size = size;
12 Node temp =head;
13 for (int i =0;i<size;i++){
14 temp .next = new Node(0);
15 temp = temp.next;
16 }
17 }
18 public BinaryQueue(String binary){ //以二進位制數建立
19 this.size = binary.length();
20 Node temp =head;
21 for (int i =0;i<size;i++){
22 temp .next = new Node(binary.charAt(i)-'0');
23 temp = temp.next;
24 }
25 }
26 public void shiftLeft(){ //左移
27 head.next = head.next.next;
28 Node temp = head.next;
29 for (int i=0;i<size;i++){
30 if (i==size-2) {
31 temp.next = new Node(0);
32 break;
33 }
34 temp = temp.next;
35 }
36 }
37 public void shiftRight(){//右移
38 Node first = head.next;
39 head.next = new Node(0);
40 head.next.next=first;
41
42 Node temp = head;
43 for (int i =0;i<size;i++){
44 temp = temp.next;
45 }
46 temp.next =null;
47 }
48 public void shiftRightArithmetically(){ //算術右移,符號擴充套件
49 Node first = head.next;
50 head.next = new Node(first.value);
51 head.next.next=first;
52
53 Node temp = head;
54 for (int i =0;i<size;i++){
55 temp = temp.next;
56 }
57 temp.next =null;
58 }
59
60 public void reverse(){
61 Node temp = head.next;
62 for (int i =0;i<size;i++){
63 temp.value = 1-temp.value; //取反,是1,1-1=0;是0:1-0=1
64 temp = temp.next;
65 }
66 }
67
68 public BinaryQueue add(BinaryQueue bq){
69 //將兩個佇列中的二進位制放入陣列中,如果長度不同則需要將短的進行算術擴充套件,
70 int len = bq.size>size?bq.size:size;
71 int [] arr_bq = new int[len];
72 int [] arr_this = new int[len];
73 if (bq.size>size){//bq 長,this擴充套件
74 String s = bq.getStr();
75 for (int i =0;i<len;i++){
76 arr_bq[i] = s.charAt(i)-'0';
77 }
78 String s_this = getStr();
79 for (int j =0 ;j<len;j++){
80 if (j<len-size){
81 arr_this[j] = head.next.value;
82 }
83 else {
84 arr_this[j]= s_this.charAt(j-(len-size))-'0';
85 }
86 }
87 }
88 else { //this 長 ,bq擴充套件
89 String s = this.getStr();
90 for (int i =0;i<len;i++){
91 arr_this[i] = s.charAt(i)-'0';
92 }
93 String s_bq = bq.getStr();
94 for (int j =0 ;j<len;j++){
95 if (j<len-size){
96 arr_bq[j] = bq.head.next.value;
97 }
98 else {
99 arr_bq[j]= s_bq.charAt(j-(len-size))-'0';
100 }
101 }
102 }
103
104 //相加
105 int []res = new int[len];
106 int carry = 0; //上一次加的進位
107 for (int i = len-1;i>=0;i--){
108 res[i] = arr_bq[i]+arr_this[i]+carry;
109 if (res[i]==2){//進位1,本位0
110 res[i]=0;
111 carry =1;
112 }
113 else if (res[i]==3){//進位1,本位1
114 res[i]=1;
115 carry =1;
116 }
117 else carry = 0;
118 }
119 String str = "";
120 for (int i =0;i<len;i++){
121 str+=res[i];
122 }
123 return new BinaryQueue(str);
124 }
125
126 public BinaryQueue getOppositeNumber(){//取相反數,就是取反加一
127 String s = "";
128 for (int i=0;i<size-1;i++){
129 s+="0";
130 }
131 s+="1";
132 reverse();//取反
133 return add(new BinaryQueue(s));//加一
134 }
135
136 public int getInt(){ //獲取二進位制所代表的補碼整數
137 if (head.next.value==1){
138 return -Integer.valueOf(getOppositeNumber().getStr(),2);
139 }
140 return Integer.valueOf(getStr(),2);
141 }
142
143
144 public String getStr(){//獲取二進位制的字串形式
145 String str ="";
146 Node temp = head.next;
147 while (temp!=null){
148 str+=temp.value;
149 temp =temp.next;
150 }
151 return str;
152 }
153
154 public static void main(String[] args) {
155 BinaryQueue bq = new BinaryQueue("1100000011");
156 BinaryQueue bq2 = new BinaryQueue("0000000000");
157 // System.out.println(bq.add(bq2).getStr());
158 // System.out.println(bq2.getOppositeNumber().getStr());
159 System.out.println(bq.getInt());
160 System.out.println(bq2.getInt());
161 }
162
163 //節點類
164 class Node{
165 int value;
166 Node next;
167 Node (int value){
168 this.value = value;
169 }
170 }
171 }
有了我們自己定義的任意N位二進位制補碼數後,我們就可能進行一些其他的操作了,比如布思演算法、整數除法等。