计算机组成原理_01_浮点数转换_代码实现_测试用例

1. 实验要求

在Transformer类中实现以下6个方法

  1. 将整数真值(十进制表示)转化成补码表示的二进制,默认长度32位
 public String intToBinary(String numStr) 
  1. 将补码表示的二进制转化成整数真值(十进制表示)
 public String binaryToInt(String binStr)
  1. 将十进制整数的真值转化成NBCD表示(符号位用4位表示)
public String decimalToNBCD(String decimal)
  1. 将NBCD表示(符号位用4位表示)转化成十进制整数的真值
public String NBCDToDecimal(String NBCDStr)
  1. 将浮点数真值转化成32位单精度浮点数表示

    • 负数以"-"开头,正数不需要正号

    • 考虑正负无穷的溢出(“+Inf”, “-Inf”,见测试用例格式)

public String floatToBinary(String floatStr)
  1. 将32位单精度浮点数表示转化成浮点数真值
    • 特殊情况同上
public String binaryToFloat(String binStr)

2. 实验攻略

本次实验推荐使用的库函数有

Integer.parseInt(String s)
Float.parseFloat(String s)
String.valueOf(int i)
String.valueOf(float f)

本次实验不允许使用的库函数有

Integer.toBinaryString(int i)
Float.floatToIntBits(float value)
Float.intBitsToFloat(int bits)

3.具体实现

3.1 整数转二进制补码

  1. 判断正负,如果为正数,则补码以0 开始,如果为负数,则补码以1 开始
  2. 常规思路:统一转化为正数,转换为补码,再根据正负,判断是否需要进行取反加1的操作。
  3. 其他思路:可以利用模系统互相等价的原理
    例如:如果我要求-3的补码,我先求 -3 + 8 = 5 的补码,最后改变符号位即可。因此,代码如下
3.1.1代码实现
public static String intToBinary(String numStr) {
        int value = Integer.parseInt(numStr);
        char[] ans = new char[32];
        Arrays.fill(ans,'0');
    	bool isNeg = false;
        if(value < 0){
            value += Math.pow(2, 31);
            isNeg = true;
        }
        int index = 31;
        while (value > 0){
            if(value % 2 == 1){
                ans[index] = '1';
            }
            index--;
            value /= 2;
        }
    	if(isNeg)
        {
            ans[0]  = '1' ;  
        }   
		return new String(ans);
    }
3.1.2 测试用例
    @Test
    public void intToBinaryTest1() {
        assertEquals("00000000000000000000000000000010", Transformer.intToBinary("2"));
    }

    @Test
    public void intToBinaryTest2() {
        assertEquals("10000000000000000000000000000000", Transformer.intToBinary("-2147483648"));
    }

    @Test
    public void intToBinaryTest3() {
        assertEquals("00000000000000000000000000001001", Transformer.intToBinary("9"));
    }

    @Test
    public void intToBinaryTest4() {
        assertEquals("00000000000000000000000000101001", Transformer.intToBinary("41"));
    }

    @Test
    public void intToBinaryTest5() {
        assertEquals("11111111111111111111111111111111", Transformer.intToBinary("-1"));
    }

3.2 二进制补码转整数

二进制转补码,也可以利用模系统互相等价的原理。
可以从 − 3 = 1101 -3 = 1101 3=1101 3 = 0011 3 = 0011 3=0011找到规律

3.2.1 代码实现
    public static String binaryToInt(String binStr) {
        char[] num = binStr.toCharArray();
        int ans = 0;
        // 计算从第1位到第31位的数字
        for(int i = 1; i < 32; i++){
            ans += (num[i] - '0') * Math.pow(2, 31 - i);
        }
        // 计算第0位的数字并减去,
        ans -= (num[0] - '0') * Math.pow(2, 31);
        return String.valueOf(ans);
    }
3.2.2 测试用例
@Test
    public void binaryToIntTest1() {
        assertEquals("2", Transformer.binaryToInt("00000000000000000000000000000010"));
    }

    @Test
    public void binaryToIntTest2() {
        assertEquals("1", Transformer.binaryToInt("00000000000000000000000000000001"));
    }

    @Test
    public void binaryToIntTest3() {
        assertEquals("2147483647", Transformer.binaryToInt("01111111111111111111111111111111"));
    }

    @Test
    public void binaryToIntTest4() {
        assertEquals("-1", Transformer.binaryToInt("11111111111111111111111111111111"));
    }

3.3 十进制数转NBCD码

规则:

  1. NBCD码的符号位是1100 代表正数,1101代表负数
  2. 默认得到的NBCD码是32位,因此可以开一个28位的char[28],并将里面填满0
  3. 首先将十进制数进行独立,也就是说通过循环取得每一位的数字,再对每一个数字digit 进行处理,转化为2进制即可
    因此,代码如下
3.3.1 代码实现
//将十进制整数的真值转化成NBCD表示(符号位用4位表示)
    public static String decimalToNBCD(String decimalStr) {
        int num = Integer.parseInt(decimalStr);
        boolean isPositive = num >= 0; // 判断是正数还是负数
        num = Math.abs(num);
        char[] ans = new char[28];
        // 额外用count代表下表,方便从右往左进行处理
        int count = 27;
        Arrays.fill(ans, '0');
        while (num != 0) {
            int digit = num % 10; //通过循环取得每一个具体的数字
            int time = 0; //额外开一个循环,循环4次,用time记录循环次数
            while (time < 4) {
                ans[count] = (char) (digit % 2 + '0');
                count--;
                digit /= 2;
                time++;
            }
            num /= 10;
        }
        if (isPositive) {
            return "1100" + new String(ans);
        } else {
            return "1101" + new String(ans);
        }
    }
3.3.2 测试用例
    @Test
    public void decimalToNBCDTest1() {
        assertEquals("11000000000000000000000000010000", Transformer.decimalToNBCD("10"));
    }

    @Test
    public void decimalToNBCDTest2() {
        assertEquals("11000000000010010000100100011001", Transformer.decimalToNBCD("90919"));
    }

    @Test
    public void decimalToNBCDTest3() {
        assertEquals("11000000000100000000000000001001", Transformer.decimalToNBCD("100009"));
    }

3.4 NBCD码转十进制数

  1. 确定正负号,判断字符串NBCD码以1100开头还是以1101开头
  2. 对NBCD码每四位进行一次处理,通过二进制转化为十进制数的方式,得到每一位digit数字。
  3. 得到每4个NBCD码代表的一位数字后,需要将其转化为十进制数,乘以10或者100……
    代码如下
3.4.1 代码实现
    //将NBCD表示(符号位用4位表示)转化成十进制整数的真值
    public static String NBCDToDecimal(String NBCDStr) {
        int ans = 0;
        int tenTime = 0;
        boolean isPositive = NBCDStr.startsWith("1100");
        /**
         * 此处额外进行了i--,所以就不需要在循环中再进行-操作了
         */
        for (int i = NBCDStr.length() - 1; i >= 4; ) {
            int time = 0;
            int tmp = 0;
            while (time < 4 && i >= 4) {
                tmp += Math.pow(2, time) * (NBCDStr.charAt(i) - '0');
                time++;
                i--;
            }
            ans += Math.pow(10, tenTime) * tmp;
            tenTime++;
        }
        /**
         * 小心-0 和 +0. 在NBCD码中需要进行区分
         */
        return isPositive ? String.valueOf(ans) : "-" + ans;

    }
3.4.2 测试用例
@Test
    public void NBCDToDecimalTest1() {
        assertEquals("10", Transformer.NBCDToDecimal("11000000000000000000000000010000"));
    }

    @Test
    public void NBCDToDecimalTest2() {
        assertEquals("90919", Transformer.NBCDToDecimal("11000000000010010000100100011001"));
    }

    @Test
    public void NBCDToDecimalTest3() {
        assertEquals("-90919", Transformer.NBCDToDecimal("11010000000010010000100100011001"));
    }

    @Test
    public void NBCDToDecimalTest4() {
        assertEquals("100509", Transformer.NBCDToDecimal("11000000000100000000010100001001"));
    }

    @Test
    public void NBCDToDecimalTest5() {
        assertEquals("-9", Transformer.NBCDToDecimal("11010000000000000000000000001001"));
    }

    @Test
    public void NBCDToDecimalTest6() {
        assertEquals("9000019", Transformer.NBCDToDecimal("11001001000000000000000000011001"));
    }

    @Test
    public void NBCDToDecimalTest7() {
        assertEquals("-9000009", Transformer.NBCDToDecimal("11011001000000000000000000001001"));
    }

    @Test
    public void NBCDToDecimalTest8() {
        assertEquals("-0", Transformer.NBCDToDecimal("11010000000000000000000000000000"));
    }

3.5 浮点数转二进制数

3.6 二进制数转浮点数

  1. 熟悉规格化数的相关表示方式,处理好NaN +Inf -Inf 、非规格化数的特殊情况
  2. 处理二进制数的字符串,将其切割为三部分:符号部分、指数部分、尾数部分
  3. 通过符号部分,判断正负号
  4. 通过指数部分,进行情况分析
  • 如果指数部分为11111111,且尾数部分全为0 ,则代表的是无穷
  • 如果指数部分为11111111,且尾数部分不全为0,则代表的是NaN
  • 如果指数部分为00000000,且尾数部分全为0,则代表的是+0-0
  • 如果指数部分为0000000,且尾数部分不全为0,则代表的是非规格化数,阶值默认为-126
  • 当阶码的值为1-254时,则进行e-127的操作,因为阶码是移码的格式,所以阶值 = 阶码真值 - 偏置常数
    32位浮点数格式
  1. 对尾数部分进行处理,将其转化为二进制数,但需要注意是小数点后的二进制,因此,是乘以 2 − i 2^{-i} 2i
  2. 最后,进行计算。
  • 如果是规格化数,则 v a l u e = 1. f ∗ 2 e x p value = 1.f*2^{exp} value=1.f2exp
  • 如果是非规格化数,则 v a l u e = 0. f ∗ 2 − 126 value = 0.f*2^{-126} value=0.f2126
  • 最后,需要小心Math.pow 返回的是double,而我们需要的是float ,因此需要强制类型转换
    代码如下
3.6.1 代码实现
    public static String binaryToFloat(String binStr) {
//        判断正负
        boolean isPos = binStr.charAt(0) == '0';
        String expStr = binStr.substring(1, 9);
        String tailStr = binStr.substring(9);
        float tailNum = 0;
//        处理指数部分
        int expNum = Integer.parseInt(expStr, 2) - 127;
        int tailCount = -1;
        float ans;
//        处理尾数部分
        for (int i = 0; i < tailStr.length(); i++) {
            tailNum += Math.pow(2, tailCount) * (tailStr.charAt(i) - '0');
            tailCount--;
        }
        if (expStr.equals("11111111")) {
            if (!tailStr.contains("1")) {
                return isPos ? "+Inf" : "-Inf";
            } else {
                return "NaN";
            }
        } else if (expStr.equals("00000000")) {
//            非规格化数,e = -126
            ans = (float) (Math.pow(2, expNum + 1) * tailNum);
        } else {
//            规格化数,尾数 = 1.xxxxxx
            tailNum += 1;
            ans = (float) (Math.pow(2, expNum) * tailNum);
        }
        return isPos ? String.valueOf(ans) : "-" + ans;
    }
3.6.2 测试用例
    @Test
    public void binaryToFloatTest1() {
        assertEquals(String.valueOf((float) Math.pow(2, -127)), Transformer.binaryToFloat("00000000010000000000000000000000"));
    }

    @Test
    public void binaryToFloatTest2() {
        assertEquals(String.valueOf((float) Math.pow(2, 127)), Transformer.binaryToFloat("01111111000000000000000000000000"));
    }

    @Test
    public void binaryToFloatTest3() {
        assertEquals(String.valueOf(1044.32), Transformer.binaryToFloat("01000100100000101000101000111101"));
    }

    @Test
    public void binaryToFloatTest4() {
        assertEquals(String.valueOf(1.32), Transformer.binaryToFloat("00111111101010001111010111000011"));
    }

    @Test
    public void binaryToFloatTest5() {
        assertEquals(String.valueOf(-0.5), Transformer.binaryToFloat("10111111000000000000000000000000"));
    }

    @Test
    public void binaryToFloatTest6() {
        assertEquals(String.valueOf(-(float) Math.pow(2, -128)), Transformer.binaryToFloat("10000000001000000000000000000000"));
    }

    @Test
    public void binaryToFloatTest7() {
        assertEquals(String.valueOf(-(float) Math.pow(2, -126)), Transformer.binaryToFloat("10000000100000000000000000000000"));
    }
    @Test
    public void binaryToFloatTest8() {
        assertEquals(String.valueOf(-(float) 0), Transformer.binaryToFloat("10000000000000000000000000000000"));
    }
    @Test
    public void binaryToFloatTest9() {
        assertEquals(String.valueOf( (float) 0), Transformer.binaryToFloat("00000000000000000000000000000000"));
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值