Programming04

题目大意

ALU.javaFPU.java中完成除法部分


补码除法

不覆盖reminder的算法,根据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

但是要注意一下这个算法实际上是会留下一个余数的并且这个余数可能会等于除数,所以要进行判断一下,把商加上1或-1(由被除数的符号决定)。

代码如下:

public class ALU {

    // 模拟寄存器中的进位标志位
    private String CF = "0";

    // 模拟寄存器中的溢出标志位
    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";
    } //特殊的位移一位方法

    /**
     * 返回两个二进制整数的除法结果 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+商末尾补充位0
        String rev=getComplement(operand2)+"000000000000000000000000000000000";// -divisor=高32位补码+低32位0+商末尾补充位0
        String ans=(operand1.charAt(0)=='1'?"11111111111111111111111111111111":"00000000000000000000000000000000")+
                    operand1+"0"; //高32位符号位+低32位被除数+补充位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&&quotient.charAt(0)==flag1?"1":"0")+quotient+reminder;
    }

}

Float除法

暂时不考虑0.significant形式的小数,处理方法类似于乘法,处理指数+截取小数除法的前23位。

要稍微注意一下,这里的除法相当于把小数部分统一成了1.xxxxx/1.xxxxx,那么答案要么是0余若干数,要么是1余若干数,因此我们把返回的商的末位,补到扩充significant时加上的0的个数对应的位数之后。

00001[补充了4个0]+significant+0000[保护位],那么最后截取的应该是:

(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);
    }

}

其实测试样例挺弱的,很简单就过了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容