題目大意
在
ALU.java
與FPU.java
中完成除法部分
補(bǔ)碼除法
不覆蓋reminder的算法遭笋,根據(jù)PPT上給出的步驟算就好了:
Extend the dividend by adding n bits sign in the front, and store it in the remainder and quotient registers
If dividend has the same sign with divisor, do subtraction; otherwise, do addition
- If the remainder has same sign with divisor, Qn=1; otherwise, Qn= 0
If the remainder has the same sign with divisor , Ri+1=2Ri-Y; otherwise, Ri+1=2Ri+Y
- If the new remainder has the same sign to divisor, set quotient to 1; otherwise, set quotient to 0
Repeat the above step
Left shift quotient, if quotient is negative (the dividend has the different sign with divisor), quotient adds 1
The remainder has the different sign with dividend
- Remainder adds divisor if the dividend has the same sign with divisor, and subtracts divisor otherwise
但是要注意一下這個(gè)算法實(shí)際上是會(huì)留下一個(gè)余數(shù)的并且這個(gè)余數(shù)可能會(huì)等于除數(shù)坝冕,所以要進(jìn)行判斷一下,把商加上1或-1(由被除數(shù)的符號(hào)決定)瓦呼。
代碼如下:
public class ALU {
// 模擬寄存器中的進(jìn)位標(biāo)志位
private String CF = "0";
// 模擬寄存器中的溢出標(biāo)志位
private String OF = "0";
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.substring(1)+"0";
} //特殊的位移一位方法
/**
* 返回兩個(gè)二進(jìn)制整數(shù)的除法結(jié)果 operand1 ÷ operand2
* @param operand1 32-bits
* @param operand2 32-bits
* @return 65-bits overflow + quotient + remainder
*/
String div(String operand1, String operand2) {
if(Pattern.matches("0{32}",operand2)){
if(!Pattern.matches("0{32}",operand1))
throw new ArithmeticException();
else return BinaryIntegers.NaN;
}else if(Pattern.matches("0{32}",operand1)) {
return "0"+BinaryIntegers.ZERO+BinaryIntegers.ZERO;
}
char flag1=operand1.charAt(0);
char flag2=operand2.charAt(0);
String divisor=operand2+"000000000000000000000000000000000"; //divisor=高32位+低32位0+商末尾補(bǔ)充位0
String rev=getComplement(operand2)+"000000000000000000000000000000000";// -divisor=高32位補(bǔ)碼+低32位0+商末尾補(bǔ)充位0
String ans=(operand1.charAt(0)=='1'?"11111111111111111111111111111111":"00000000000000000000000000000000")+
operand1+"0"; //高32位符號(hào)位+低32位被除數(shù)+補(bǔ)充位0
if(flag1==flag2)
ans=add(ans,rev);
else ans=add(ans,divisor);
if(ans.charAt(0)==flag2) {
ans=ans.substring(0,ans.length()-1)+"1";
}
for(int i=0;i<32;i++){
if(ans.charAt(0)==flag2) {
ans=shift(ans);
ans=add(ans,rev);
}else{
ans=shift(ans);
ans=add(ans,divisor);
}
if(ans.charAt(0)==flag2)
ans=ans.substring(0,ans.length()-1)+"1";
}
String quotient=ans.substring(32,65);
String reminder=ans.substring(0,32);
quotient = shift(quotient).substring(0,32);
if(quotient.charAt(0)=='1')
quotient = add(quotient, "00000000000000000000000000000001");
if(reminder.charAt(0)!=flag1) {
if (flag1 == flag2)
reminder = add(reminder, operand2);
else
reminder=add(reminder,getComplement(operand2));
}
if(reminder.equals(getComplement(operand2))){
reminder="00000000000000000000000000000000";
quotient=add(quotient,getComplement("00000000000000000000000000000001"));
}else if(reminder.equals(operand2)) {
reminder="00000000000000000000000000000000";
quotient=add(quotient, "00000000000000000000000000000001");
}
return (flag2!='0'&&flag1==flag2&"ient.charAt(0)==flag1?"1":"0")+quotient+reminder;
}
}
Float除法
暫時(shí)不考慮0.significant形式的小數(shù)喂窟,處理方法類似于乘法,處理指數(shù)+截取小數(shù)除法的前23位央串。
要稍微注意一下磨澡,這里的除法相當(dāng)于把小數(shù)部分統(tǒng)一成了1.xxxxx/1.xxxxx,那么答案要么是0余若干數(shù)质和,要么是1余若干數(shù)稳摄,因此我們把返回的商的末位,補(bǔ)到擴(kuò)充significant時(shí)加上的0的個(gè)數(shù)對(duì)應(yīng)的位數(shù)之后饲宿。
00001[補(bǔ)充了4個(gè)0]+significant+0000[保護(hù)位]厦酬,那么最后截取的應(yīng)該是:
(quotient.charAt(end-1)+reminder[4...]).substring(indexOf('1')+1,indexOf('1')+24)
如果indexOf('1')不為0,還需要加到ex上褒傅。
代碼如下:
public class FPU {
/**
* compute the float mul of a / b
*/
String div(String a, String b) {
char flag=a.charAt(0)==b.charAt(0)?'0':'1';
if(Pattern.matches("[01]0{31}",b))
if(Pattern.matches("[01]0{31}",a)) return IEEE754Float.NaN;
else throw new ArithmeticException();
if(Pattern.matches("1{8}0{23}",a.substring(1,a.length()))||Pattern.matches("[01]0{31}",a))
return flag+a.substring(1,a.length());
ALU alu=new ALU();
String ex=alu.add(a.substring(1,9),alu.add(ALU.getComplement(b.substring(1,9)),"01111111"));
String sig=alu.div("00001"+a.substring(9,32)+"0000","00001"+b.substring(9,32)+"0000");
sig=sig.charAt(32)+sig.substring(38);
for(int i=0;i<sig.indexOf('1');i++)
ex=alu.add(ex,"11111111");
return flag+ex+sig.substring(sig.indexOf('1')+1,sig.indexOf('1')+24);
}
}
其實(shí)測(cè)試樣例挺弱的弃锐,很簡(jiǎn)單就過了。