ALU底層方法及計算機整數加減乘除模擬
阿新 • • 發佈:2018-12-20
ALU是計算機CPU的核心,即 算術邏輯單元(arithmetic and logic unit)
ALU有幾大功能,是計算機計算最基礎的功能:
1.算術運算:包含加法、減法等
2.邏輯運算:主要是布林運算,邏輯和、或、非、異或等
3.求補器:計算機中,二進位制補碼極其重要,可以求一個二進位制的補碼(原始碼取反得反碼,反碼加一得補碼)
4.移位器:主要有 算術右移、邏輯右移、左移
5.狀態標誌:一個記錄狀態的標誌。
4 /**
5 以下加法減法等都預設是相同長度的,如果長度不同會報錯,當然,我只是懶得處理。 20 */
21
22 public class ALU {
23
24 /**
25 * 返回一個整數的定長二進位制字串(補碼)
26 *
27 * @param len 指定長度
28 */
29 public String Int2Binary(int n, int len) {
30 // return Integer.toBinaryString(n);//注意,這個方法返回的是無符號的二進位制,而且長度隨引數而變的,故不可行,但是負數是可行的,負數返回32位
31 String s = "";
32 for (int i = len - 1; i >= 0; i--) {
33 s += ((n >> i) & 1) == 1 ? "1" : "0";
34 }
35 return s;
36 }
37
38 /**
39 * 預設長度,即可以滿足的最小長度
40 */
41 public String Int2Binary(int n) {
42 if (n == 0) return "0";
43 if (n > 0) {
44 return "0" + Integer.toBinaryString(n);
45 } else {
46 return getNegative("0" + Integer.toBinaryString(-n));
47 }
48 }
49
50 public int binary2Int(String binary) {
51 return 0;
52 }
53
54 /**
55 * 加法器:計算兩個二進位制的和
56 *
57 * @param binary1
58 * @param binary2 必須相同長度
59 * @return 返回len+1長度: 最高位進位+和
60 */
61 public String add(String binary1, String binary2) {
62 int[] res = new int[binary1.length()];
63 int carry = 0;
64 for (int i = binary1.length() - 1; i >= 0; i--) {
65 res[i] = binary1.charAt(i) - '0' + binary2.charAt(i) - '0' + carry;
66 if (res[i] == 2) {
67 carry = 1;
68 res[i] = 0;
69 } else if (res[i] == 3) {
70 carry = 1;
71 res[i] = 1;
72 } else carry = 0;//無進位,前面一個進位置0
73 }
74 String result = "";
75 for (int i = 0; i < res.length; i++) {//res中存放的是正的順序,沒有反
76 result += res[i];
77 }
78 return carry + result;
79 }
80
81 public String substract(String a, String b) {//a-b = a+(-b) ,注意,多了一個最高位
82 return add(a, getNegative(b));
83 }
84
85 public String get01(int n, String zeroORone) {
86 String res = "";
87 for (int i = 0; i < n; i++) {
88 res += zeroORone;
89 }
90 return res;
91 }
92
93 public String shiftRightLogically(String binary) {
94 return "0" + binary.substring(0, binary.length() - 1);
95 }
96
97 public String shiftLeft(String binary) {
98 return binary.substring(1) + "0";
99 }
100
101 /**
102 * 算術右移
103 */
104 public String shiftRight(String binary) {
105 return binary.charAt(0) + binary.substring(0, binary.length() - 1);
106 }
107
108 /**
109 * 取補碼(相反數)
110 */
111 public String getNegative(String binary) {
112 return add(getComplement(binary), get01(binary.length() - 1, "0") + "1").substring(1);//add有一個最高位進位判斷,去掉;
113 }
114
115 /**
116 * 取反碼
117 */
118 public String getComplement(String binary) {
119 String res = "";
120 for (int i = 0; i < binary.length(); i++) {
121 res += (binary.charAt(i) == '1' ? "0" : "1");
122 }
123 return res;
124 }
125
126 /**
127 * 整數乘法,布思演算法
128 */
129 public String multiply(String Q, String M) {
130 char Q0 = '0';
131 String A = get01(Q.length(), "0");
132 for (int i = 0; i < Q.length(); i++) {
133 String QQ0 = Q.charAt(Q.length() - 1) + "" + Q0;//不能把兩個char字元放在一起,會變成加
134 System.out.println(QQ0);
135 if (QQ0.equals("10")) {
136 A = substract(A, M).substring(1);
137 } else if (QQ0.equals("01")) {
138 A = add(A, M).substring(1);
139 }
140 String temp = shiftRight(A + Q + Q0);
141 A = temp.substring(0, A.length());
142 Q = temp.substring(A.length(), 2 * A.length());
143 Q0 = temp.charAt(temp.length() - 1);
144 }
145 return A + Q;
146 }
147
148 public String[] divide(String a, String b) { // a/b
149 String A = get01(a.length(), a.substring(0, 1));//附加暫存器,存放Q的擴充套件位,初始化為等位的被除數左擴位(1/0)
150 String Q = a; //被除數算術左擴為2n然後存到暫存器Q,注意A就是擴充套件位,擴充套件位不存在Q中,即AQM三個都等長
151 String M = b;//除數放到暫存器M
152 for (int i = 0; i < a.length(); i++) {
153 char A_sign = A.charAt(0);
154
155 //A Q 左移1位
156 String temp = shiftLeft(A + Q);
157 A = temp.substring(0, a.length());
158 Q = temp.substring(a.length());
159
160 //判斷MA是否同號
161 if (M.charAt(0) == A.charAt(0)) {// A M has same sign
162 A = substract(A, M).substring(1);
163 }
164 else {
165 A = add(A, M).substring(1);
166 }
167
168 //判斷A的符號變化沒有;
169 if (A_sign == A.charAt(0) || !A.contains("1")) {//A符號沒變,或者A=0(不含“1”即全0);
170 Q = Q.substring(0, Q.length() - 1) + "1"; //Q0=1
171 }
172 else {//A的符號變了,且A!=0
173 Q = Q.substring(0, Q.length() - 1) + "0"; //Q0=0
174 A = add(A, M).substring(1); //A =A+M 恢復;
175 }
176 }
177 String[] res = new String[2]; //返回0:商,1:餘數
178 res[0] = (a.charAt(0) == b.charAt(0)) ? Q : getNegative(Q);//商在Q中,如果除數被除數不同號,則取補碼
179 res[1] = A;//餘數在A中
180 return res;
181 }
182
183 public static void main(String[] args) {
184 ALU s = new ALU();
185 System.out.println(s.Int2Binary(5, 12));
186 System.out.println(s.add("111", "111"));
187 System.out.println(s.get01(12, "1"));
188 System.out.println(s.shiftLeft("111111"));
189 System.out.println(s.shiftRight("011111"));
190 System.out.println(s.shiftRightLogically("111111"));
191 System.out.println(s.getComplement("111111100011"));
192 System.out.println(s.getNegative("1000100"));
193 System.out.println(s.Int2Binary(-12));
194 System.out.println(s.multiply("011", "011"));//3X3=9
195 System.out.println(s.multiply("1001", "0101"));//-7X3=-35
196
197 System.out.println(s.divide("01111","00010")[0]+"..."+s.divide("01111","00010")[1]);//15/2=7...1
198 }
199 }
output:
000000000101
1110
111111111111
111110
001111
011111
000000011100
0111100
10100
10
11
01
001001
10
01
00
10
11011101
00111...00001