题目大意
在
ALU.java
与FPU.java
中完成乘法部分
ALU部分
取成64位的串,调用一下之前写过的加法和位移,最后截取低32位就好了。
代码很简单,稍微抄了一下之前取补码的那个方法:
public class ALU {
private StringBuilder ans=new StringBuilder();
public static String getComplement(String tar) {
tar = tar.replace("0", "2").replace("1", "0").replace("2", "1");
char[] status = tar.toCharArray();
for (int i = tar.length() - 1, jud = 1; i >= 0; i--) {
status[i] = (char) ((jud ^ (tar.charAt(i) - '0')) + '0');
jud = ((tar.charAt(i) - '0') & jud);
}
return Arrays.toString(status).replaceAll("[\\[\\]\\s,]", "");
}
String add(String src, String dest) {
ans=new StringBuilder();
int c=0,s=0;
for(int i=dest.length()-1;i>=0;i--){
int x=src.charAt(i)-'0',y=dest.charAt(i)-'0';
s=x^y^c;
c=(x&c)|(y&c)|(x&y);
ans.append(s);
}
return ans.reverse().toString();
}
String shift(String src){
return (src.charAt(0)=='1'?"1":"0")+src.substring(0,src.length()-1);
} //特殊的位移一位方法
/**
* 返回两个二进制整数的乘积(结果直接截取后32位)
* 要求使用布斯乘法计算
* @param src 32-bits
* @param dest 32-bits
* @return 32-bits
*/
String mul (String src, String dest,String...args){
dest="00000000000000000000000000000000"+dest+"0";
String rev=getComplement(src);
src=src+"000000000000000000000000000000000";
rev=rev+"000000000000000000000000000000000";//33个零,扩展到65位
for(int i=0;i<32;i++){
if(dest.charAt(64)-dest.charAt(63)==1)
dest=add(src,dest);
else if(dest.charAt(64)-dest.charAt(63)==-1)
dest=add(rev,dest);
dest=shift(dest);
}
if(args.length==0)
return dest.substring(32,64);
else return dest;
}
}
FPU部分
这部分怎么说呢,指数相加,但是注意相当于多加了一个bias,直接加的结果要减去对应的这个bias.想来助教应该不会刁钻到出float的非规约形式,即0.significant的结构,因此直接在23位前补上1.就好了。同时看了看测试样例,可以说是非常弱的数据,所以指数不用考虑溢出直接写就好了。
写的是否发现要注意一下a为0的情况,需要判断b是Inf或NaN:
package cpu.alu;
import util.IEEE754Float;
import java.util.regex.Pattern;
/**
* floating point unit
* 执行浮点运算的抽象单元
* 浮点数精度:使用4位保护位进行计算,计算完毕直接舍去保护位
* TODO: 浮点数运算
*/
public class FPU {
/**
* compute the float mul of a * b
* 分数部分(23 bits)的计算结果直接截取前23位
*/
String mul(String a, String b) {
char flag=a.charAt(0)==b.charAt(0)?'0':'1';
if(Pattern.matches("0{31}",a.substring(1,32)))
if(Pattern.matches("1{8}",b.substring(1,9)))
return "(0|1){1}1{8}(0+1+|1+0+)(0|1)*";
else return flag+a.substring(1,32);
ALU alu=new ALU();
String ex=alu.add(a.substring(1,9),alu.add(b.substring(1,9),"10000001"));
String sig=alu.mul("000000001"+a.substring(9,32),"000000001"+b.substring(9,32),"not cut");
return flag+ex+sig.substring(sig.indexOf('1')+1,sig.indexOf('1')+24);
}
}
测试一下,都通过了。