要得到补码,首先要能将真值的十进制转换为64位原码,从而得到64位反码,最后得到64位补码。
因此包含以下功能模块:
result[i] = num % 2 == 0 ? '0' : '1';
num /= 2;
result[i] = result[i] == '1' ? '0' : '1';
temp = FullAdder.getS(result[i], '0', c);
c = FullAdder.getC(result[i], '0', c);
result[i] = temp;
二进制机器码转十六进制64位的二进制机器数可以说是相当的冗长,不便于开发者进行调试,因此需要开发一个方法将二进制机器码以16进制形式输出在终端上。
按照人工手算二进制转十六进制的方法,每四位划分一组,每组分别计算出一个十六进制数字,并进行字符串累加即可。
final static char[] hexCharacters = "0123456789ABCDEF".toCharArray();
private static String BtoH(char[] chars) {String result = "0x";
for (int i = 0; i<= 15; i++) {int tag = 0;
for (int j = 0; j<= 3; j++) {tag += chars[4 * i + j] == '1' ? Math.pow(2, 3 - j) : 0;
}
result += hexCharacters[tag];
}
return result;
}
一位全加器的实现在计算机组成原理中,我们学习了一位全加器74LS181的功能与逻辑表达式:
S
i
=
A
i
⊕
B
i
⊕
C
i
C
i
+
1
=
A
i
B
i
+
(
A
i
+
B
i
)
C
i
S_i=A_i\oplus B_i \oplus C_i \\C_{i+1}=A_iB_i+(A_i+B_i)C_i
Si=Ai⊕Bi⊕CiCi+1=AiBi+(Ai+Bi)Ci
因此要得到
S
i
、
C
i
+
1
S_i、C_{i+1}
Si、Ci+1,只需要分别按照两个逻辑表达式分别写两个方法即可。
S i S_i Si:
return x=='1'^y=='1'^c=='1'?'1':'0';
C i + 1 C_{i+1} Ci+1:
return (x=='1'&&y=='1')||((x=='1'||y=='1')&&c=='1')?'1':'0';
模四补码加法模四补码加法的双符号位使得溢出判断变得简单。
计算完成后,如果双符号位分别为
11或00:未溢出
10:下溢出
01:上溢出
由于使用了大小为64的字符数组,因此要实现双符号位,只需要额外再声明一个syn变量作为最高位符号位即可。判断溢出的时候,只需要将syn与字符数组的最高位进行比较、判断。
char syn = FullAdder.getS(xChar[0], yChar[0], c);
//00或11
if (result[0] == syn) {System.out.println("结果未溢出\n");
}
//10
else if (syn == '1')
System.out.println("结果下溢出\n");
//01
else
System.out.println("结果上溢出\n");
64位补码转换为十进制真值补码加法得到的结果为一个补码,要将补码先转换为原码,再将原码转换为真值。
补码转原码,已经实现了,只需要套用原码转补码的方法就可以,一个字都不用改。
原码转真值,只需要按位乘以权重,再进行累加即可。
num += result[i] == '1' ? Math.pow(2, 63 - i) : 0;
代码实现
一位全加器的实现FullAdder.java
public class FullAdder {public static char getS(char x,char y,char c){return x=='1'^y=='1'^c=='1'?'1':'0';
}//得到Si
public static char getS(char x,char y){return getS(x,y,'0');
}
public static char getC(char x,char y,char c){return (x=='1'&&y=='1')||((x=='1'||y=='1')&&c=='1')?'1':'0';
}//得到进位位Ci
public static char getC(char x,char y){return getC(x,y,'0');
}
}
转换、计算功能的实现public class BinaryComputing {final static char[] hexCharacters = "0123456789ABCDEF".toCharArray();
//二进制转十六进制
private static String BtoH(char[] chars) {String result = "0x";
for (int i = 0; i<= 15; i++) {int tag = 0;
for (int j = 0; j<= 3; j++) {tag += chars[4 * i + j] == '1' ? Math.pow(2, 3 - j) : 0;
}
result += hexCharacters[tag];
}
return result;
}
//输入十进制真值得到原码的二进制形式
private static char[] getTrueFormBinary(long num) {char[] result = new char[64];
//符号位
result[0] = num >= 0 ? '0' : '1';
if (num< 0) num = -num;
//除2取余
for (int i = 63; i >0; i--) {result[i] = num % 2 == 0 ? '0' : '1';
num /= 2;
}
return result;
}
//输入十进制真值得到补码的二进制形式
private static char[] getCompletionFormBinary(long num) {char[] result = getTrueFormBinary(num);
return getCompletionFormBinary(result);
}
//输入十进制真值得到补码的二进制形式
private static char[] getCompletionFormBinary(char[] result) {//原码为正数时,无需操作
if (result[0] == '0') return result;
//按位取反得到反码
for (int i = 1; i< 64; i++) {result[i] = result[i] == '1' ? '0' : '1';
}
//使用一位全加器进行末位加1操作
char c = '1', temp;
for (int i = 63; i >0; i--) {temp = FullAdder.getS(result[i], '0', c);
c = FullAdder.getC(result[i], '0', c);
result[i] = temp;
if (c == '0') break;
}
return result;
}
//输入二进制原码得到十进制真值
public static long trueFormToNum(char[] result) {long num = 0;
for (int i = 1; i< 64; i++) {num += result[i] == '1' ? Math.pow(2, 63 - i) : 0;
}
return result[0] == '0' ? num : -num;
}
//输入二进制补码得到十进制真值
public static long completionFormToNum(char[] result) {result = getCompletionFormBinary(result);
return trueFormToNum(result);
}
//输入十进制真值得到十六进制原码
public static String getTrueFormHex(long num) {return BtoH(getTrueFormBinary(num));
}
//输入十进制真值得到十六进制补码
public static String getCompletionFormHex(long num) {return BtoH(getCompletionFormBinary(num));
}
//加法器
public static long adder(long x, long y) {char[] xChar = getCompletionFormBinary(x), yChar = getCompletionFormBinary(y);
char[] result = new char[64];
System.out.println("转换得到x补码为" + BtoH(xChar) + "\n");
System.out.println("转换得到y补码为" + BtoH(yChar) + "\n");
char c = '0';
for (int i = 63; i >= 0; i--) { //利用一位全加器进行串行加法计算
result[i] = FullAdder.getS(xChar[i], yChar[i], c);
c = FullAdder.getC(xChar[i], yChar[i], c);
}
//声明syn变量作为拓展符号位
char syn = FullAdder.getS(xChar[0], yChar[0], c);
//判断溢出情况
if (result[0] == syn) {System.out.println("结果未溢出\n");
}
else if (syn == '1')
System.out.println("结果下溢出\n");
else
System.out.println("结果上溢出\n");
System.out.println("结果的补码(16进制)为:" + BtoH(result) + "\n");
//补码转真值
return completionFormToNum(result);
}
//减法器:x-y=x+(-y)
public static long subtractor(long x,long y){return adder(x,-y);
}
}
测试样例Test1.java
import java.util.Scanner;
public class Test1 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);
String scIn;
long a, b;
System.out.println("请输入x、y:\n");
a = sc.nextLong();
b = sc.nextLong();
System.out.println("\nx+y:\n");
System.out.println("结果为"+BinaryComputing.adder(a, b)+"\n");
System.out.println("\nx-y:\n");
System.out.println("结果为"+BinaryComputing.subtractor(a, b)+"\n");
}
}
输入
-23 59
输出
请输入x、y:
-23 59
x+y:
转换得到x补码为0xFFFFFFFFFFFFFFE9
转换得到y补码为0x000000000000003B
结果未溢出
结果的补码(16进制)为:0x0000000000000024
结果为36
x-y:
转换得到x补码为0xFFFFFFFFFFFFFFE9
转换得到y补码为0xFFFFFFFFFFFFFFC5
结果未溢出
结果的补码(16进制)为:0xFFFFFFFFFFFFFFAE
结果为-82
希望对读者有所帮助
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧