Java实现64位定点数整数补码加减法-创新互联

Java实现定点整数补码加减法
  • 技术要点
    • 真值转换为64位补码
    • 二进制机器码转十六进制
    • 一位全加器的实现
    • 模四补码加法
    • 64位补码转换为十进制真值
  • 代码实现
    • 一位全加器的实现
    • 转换、计算功能的实现
    • 测试样例

Java的相关文章已经有很多了,很多前辈也分享了很多很多编程经验与技巧。本文是我在学习Java过程中有感而发,代码实现计组的定点整数加减法的过程,希望对读者有帮助。
本课题要求编写一个程序:
① 输入:两个长整数
② 输出:两个数的和、差
③ 使用Java,计算过程要模拟手算64位定点整数加减法的过程,且使用字符数组储存二进制机器数。

坚守“ 做人真诚 · 做事靠谱 · 口碑至上 · 高效敬业 ”的价值观,专业网站建设服务10余年为成都食品包装袋小微创业公司专业提供企业网站建设营销网站建设商城网站建设手机网站建设小程序网站建设网站改版,从内容策划、视觉设计、底层架构、网页布局、功能开发迭代于一体的高端网站建设服务。
技术要点 真值转换为64位补码

要得到补码,首先要能将真值的十进制转换为64位原码,从而得到64位反码,最后得到64位补码。
因此包含以下功能模块:

  • 十进制转二进制:使用除2取余法即可。
result[i] = num % 2 == 0 ? '0' : '1';
num /= 2;
  • 二进制补全为64位原码:符号位根据正负填充1、0,空位用0填充。
  • 64位原码各位取反得到64位反码:用一个循环以及逻辑非。
result[i] = result[i] == '1' ? '0' : '1';
  • 64位反码末位加1得到64位补码:开发一个全加器用于末位加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​⊕Ci​Ci+1​=Ai​Bi​+(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元起,快前往官网查看详情吧


新闻标题:Java实现64位定点数整数补码加减法-创新互联
分享网址:http://csdahua.cn/article/dgjeed.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流