当前位置:   article > 正文

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

真值转浮点数

1. 实验要求

Transformer类中实现以下6个方法

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

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

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

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

2. 实验攻略

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

Integer.parseInt(String s)
Float.parseFloat(String s)
String.valueOf(int i)
String.valueOf(float f)
  • 1
  • 2
  • 3
  • 4

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

Integer.toBinaryString(int i)
Float.floatToIntBits(float value)
Float.intBitsToFloat(int bits)
  • 1
  • 2
  • 3

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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
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"));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
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"));
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

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);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
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"));
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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;

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
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"));
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
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"));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/258461
推荐阅读
相关标签
  

闽ICP备14008679号