COA代码解析

Transformer

intToBinary()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 整数转二进制
*
* @param 字符串表示的十进制整数
* @return 将十进制转化为二进制数的字符串
*/
public String intToBinary(String numStr) {
int num = Integer.parseInt(numStr);
StringBuilder numBinary = new StringBuilder(Integer.toBinaryString(num));
int len = numBinary.length();
for (int i = 0; i < 32 - len; i++) {
numBinary.insert(0, "0");
}
return numBinary.toString();
}
1
2
3
4
5
6
7
8
public String intToBinary(String numStr) {
String res = "";
for (int i = 0; i < 32; i++) {
res += numStr & 1;
numStr >> 1;
}
return res;
}

调用库函数Integer.toBinaryString(num) 将字符串长度补全为32位

binaryToInt()

1
2
3
4
5
6
7
8
9
10
/**
* 二进制转整数
*
* @param binStr : Binary string in 2's complement
* @return :result
*/
public String binaryToInt(String binStr) {
int num = Integer.parseUnsignedInt(binStr, 2);
return String.valueOf(num);
}

调用库函数Integer.parseUnsignedInt(binstr, 2)

decimalToNBCD()

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
/**
* 整数转NBCD码
*
* @param decimalStr 字符串表示的十进制整数
* @return result 转换出的NBCD码
*/
public String decimalToNBCD(String decimalStr) {
StringBuilder numBCD = new StringBuilder();
if (decimalStr.startsWith("-")) {
//优先判断符号位,将符号存入结果中
numBCD.append("1101");
decimalStr = decimalStr.substring(1, decimalStr.length());
} else {
numBCD.append("1100");
}
for (int i = 0; i < decimalStr.length(); i++) {
StringBuilder partBCD = new StringBuilder(Integer.toBinaryString(decimalStr.charAt(i) - 48));
int len = partBCD.length();
for (int j = 0; j < 4 - len; j++) {
partBCD.insert(0, "0");
}
numBCD.append(partBCD);
}

int len = numBCD.length();
for (int i = 0; i < 32 - len; i++) {
numBCD.insert(4, "0");
}

return numBCD.toString();
}

NBCD码:将每一位数转化为4位二进制串并拼接,并在头部添加符号

负号:1101 正号:1100

代码亦可使用键值对(将每一位数字与4位字符串一一对应)直接实现

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
/**
* 整数转NBCD码
*
* @param decimalStr 字符串表示的十进制整数
* @return result 转换出的NBCD码
*/
public String decimalToNBCDAno(String decimalStr) {
HashMap<Character, String> intToNBCDS;
//生成哈希表
intToNBCDS.append('-', "1101");
intToNBCDS.append('0', "0000");
intToNBCDS.append('1', "0001");
//中间省略
intToNBCDS.append('8', "1000");
intToNBCDS.append('9', "1001");
StringBuilder res = new StringBuilder();
for (int i = 0; i < decimalStr.length(); i++) {
res.append(intToNBCDS.get(decimalStr.charAt(i)));
//逐位分离整数,并将每一位作为键在哈希表中获取对应4位字符串并添加到res中
}

if (!res.startsWith("1101")) {
//正数补充符号位
res.insert(0, "1100");
}

return res.toString();
}

NBCDToDecimal()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* NBCD转整数
* @param NBCDStr NBCD码
* @return result 字符串形式的十进制整数
* */
public String NBCDToDecimal(String NBCDStr) {
StringBuilder numStr = new StringBuilder();
for (int i = NBCDStr.length() - 4; i > 3; i = i - 4) {
//跳过符号位,每4位为一组分离转化,并添加到numstr中
numStr.insert(0, Integer.parseInt(NBCDStr.substring(i, i + 4), 2));

}
if (NBCDStr.startsWith("1101")) {
numStr.insert(0, '-');
}
return String.valueOf(num);
}

floatToBinary()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
* 浮点数转二进制字符串:
* 1、特判无穷大,返回+Inf或-Inf
* 2、为方便计算,取绝对值
* 3、算阶,同时判断是否是规格化数,规格化数的阶的范围是[-126, 127],非规格化数的阶是-126
* 4、计算去除隐藏位的有效位数值,规格化数要减1,非规格化数不需要
* 5、循环计算出长度为23的有效位二进制字符串
* 6、根据正负号返回结果
* @param floatStr : The string of the float true value
* */
public String floatToBinary(String floatStr) {
// 特判无穷大的情况
// Float.POSITIVE_INFINITY表示Float类型的正无穷大
// Float.NEGATIVE_INFINITY表示Float类型的负无穷大

if (Float.parseFloat(floatStr) == Float.POSITIVE_INFINITY) {
return "+Inf";
} else if (Float.parseFloat(floatStr) == Float.NEGATIVE_INFINITY) {
return "-Inf";
}

// 取绝对值
String abs = floatStr;
if (floatStr.charAt(0) == '-') {
abs = floatStr.substring(1);
}
String expStr;
// 阶码
String sigStr = "";
// 尾码

// 算阶
int exp;
boolean isNormalized = true;
// 规格化数的阶的范围是[-126, 127]
for (exp = -126; ; exp++) {
if (Math.pow(2, exp) <= Float.parseFloat(abs) && Float.parseFloat(abs) < Math.pow(2, exp + 1)) {
break;
}
// 计算阶码(十进制整数)
// 非规格化数,阶一定是-126
if (exp == 128) {
exp = -126;
isNormalized = false;
break;
}
}
if (!isNormalized) {
expStr = "00000000";
// 算有效位
double sig = Float.parseFloat(abs) / Math.pow(2, exp);
// 不需要减一
for (int i = 0; i < 23; i++) {
sig = sig * 2;
if (sig >= 1) {
sigStr += "1";
sig -= 1;
} else {
sigStr += "0";
}
}
if (floatStr.charAt(0) == '-') {
return "1" + expStr + sigStr;
}
return "0" + expStr + sigStr;
}
expStr = Integer.toBinaryString(exp + 127);
int expStrLen = expStr.length();
for (int i = 0; i < 8 - expStrLen; i++) {
expStr = "0" + expStr;
}
// exp已计算完毕,包括补齐8位
// 算有效位
double sig = Float.parseFloat(abs) / Math.pow(2, exp) - 1;
for (int i = 0; i < 23; i++) {
sig = sig * 2;
// 先乘二
if (sig >= 1) {
sigStr += "1";
sig -= 1;
} else {
sigStr += "0";
}
}
if (floatStr.charAt(0) == '-') {
return "1" + expStr + sigStr;
}
return "0" + expStr + sigStr;
}

binaryToFloat()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* 二进制字符串转浮点数:
* 1、判断无穷大的特殊情况
* 2、将阶转换成整数并判断是否是规格化数
* 3、非规格化数的阶是-126,规格化数的阶转换成整数后-127
* 4、计算加上隐藏位后的有效位,规格化数的隐藏位是1,非规格化数是0
* 5、根据正负号返回结果
* 6、注意,返回结果的数值是double类型,否则精度不准
* Binary code to its float true value
* */
public String binaryToFloat(String binStr) {
if (binStr.equals("01111111100000000000000000000000")) {
return "+Inf";
} else if (binStr.equals("11111111100000000000000000000000")) {
return "-Inf";
}
String expStr = binStr.substring(1, 9);
boolean isNormalized = true;
if (expStr.equals("00000000")) {
isNormalized = false;
}
int exp;
double sig = 0;
// 规格化数尾数省略位为1
// 非规格化数尾数省略位0
double res;
if (!isNormalized) {
exp = -126;
for (int i = 0; i < 23; i++) {
if (binStr.charAt(9 + i) == '1') {
sig += Math.pow(2, -(i + 1));
}
}
res = Math.pow(2, exp) * sig;
if (binStr.charAt(0) == '1') {
return String.valueOf(-res);
}
return String.valueOf(res);
}

exp = Integer.parseInt(expStr, 2) - 127;

sig = 1;

for (int i = 0; i < 23; i++) {
if (binStr.charAt(9 + i) == '1') {
sig += Math.pow(2, -(i + 1));
}
}
res = Math.pow(2, exp) * sig;
if (binStr.charAt(0) == '1') {
return String.valueOf(-res);
}
return String.valueOf(res);
}

ALU

add()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 返回两个二进制整数的和
* dest + src
*
* @param src 32-bits
* @param dest 32-bits
* @return 32-bits
*/
public DataType add(DataType src, DataType dest) {
String first = src.toString();
String second = dest.toString();
StringBuilder result = new StringBuilder();
int temp = 0;
// 表示进位
for (int i = 31; i >= 0; i--) {
result.insert(0, (char) (((first.charAt(i) - 48) + (second.charAt(i) - 48) + temp) % 2 + 48));
temp = ((first.charAt(i) - 48) + (second.charAt(i) - 48) + temp) / 2;
}

return new DataType(result.toString());
}

sub()

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
/**
* 返回两个二进制整数的差
* dest - src
*
* @param src 32-bits
* @param dest 32-bits
* @return 32-bits
*/
public DataType sub(DataType src, DataType dest) {
DataType inSrc = buma(src);

return add(inSrc, dest);
}

/**
* 返回src的补码字符串
* @param src 要转换的数字的字符串形式
* @return 补码
*/
public DataType buma(DataType src) {
String srcChars = src.toString();
StringBuilder inChars = new StringBuilder();

DataType one = new DataType("00000000000000000000000000000001");
for (int i = 0; i < 32; i++) {
if (srcChars.charAt(i) == '0') {
inChars.append("1");
} else {
inChars.append("0");
}
}
// 取反操作

return add(new DataType(inChars.toString()), one);
// 直接调用add做+1操作
}

将减数转换为补码直接调用加法即可

mul()

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
43
44
45
46
47
48
49
50
51
/**
* 返回两个二进制整数的乘积(结果低位截取后32位)
* dest * src
*
* @param src 32-bits
* @param dest 32-bits
* @return 32-bits
*/
public DataType mul(DataType src, DataType dest) {
String destStr = dest.toString();

StringBuilder res = new StringBuilder();
for (int i = 0; i < this.length; i++) {
res.append(destStr.charAt(i));
}

for (int i = this.length; i >= 0; i--) {
res.insert(0, "0");
}
// 补齐为65位
// 初始化完成;
// temp共65位长;
// 前面补32个0,最后补一个0
destChars += "0";
// 因为要从最后一位开始减,所以补一个0防止越界
for (int i = 0; i < this.length; i++) {
// 如果前一位减后一位为1
if (destStr.charAt(this.length - i) - destStr.charAt(this.length - i - 1) == 1) {
res = new StringBuilder(add(new DataType(res.substring(0, this.length)), src) + res.substring(this.length));
// temp 0-32 位与srcChars做加法运算
res.insert(0, "1");
res.deleteCharAt(res.length() - 1);
// 右移,头部添加1
continue;
// 判断完就进入下一循环,不可进入下个if
}
if (destStr.charAt(this.length - i) - destStr.charAt(this.length - i - 1) == -1) {
res = new StringBuilder(sub(src, new DataType(res.substring(0, this.length))) + res.substring(this.length));
}
res.insert(0, "0");
res.deleteCharAt(res.length() - 1);
// 右移
}
// 前一位减后一位等于-1 或 前一位等于后一位 尾部都添加0


res.deleteCharAt(res.length() - 1);
// 最后右移

return new DataType(res.substring(this.length));
}

div()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* 返回两个二进制整数的除法结果
* 请注意使用不恢复余数除法方式实现
* dest ÷ src
*
* @param src 32-bits
* @param dest 32-bits
* @return 32-bits
*/
public DataType div(DataType src, DataType dest) {
String divedNum = dest.toString();
String divNum = src.toString();

if (divNum.indexOf('1') == -1) {
throw new ArithmeticException();
}
//判断除数为0;

if (divNum.equals(divedNum)) {
remainderReg = new DataType("00000000000000000000000000000000");
return new DataType("00000000000000000000000000000001");
}
//判断除数与被除数相等;

if (divedNum.indexOf('1') == -1) {
remainderReg = new DataType("00000000000000000000000000000000");
return new DataType("00000000000000000000000000000000");
}
//被除数为0;

if("10000000000000000000000000000000".equals(divedNum)) {
remainderReg = new DataType("00000000000000000000000000000000");
return new DataType("10000000000000000000000000000000");
}
//溢出特判;

char signDivedNum = divedNum.charAt(0);
char signDivNum = divNum.charAt(0);
char signReminer = signDivedNum;

if (signDivNum != signDivedNum) {
if (signDivNum == '1') {
// 不同号的情况下:
// 除数符号取反使符号相同然后递归
divNum = abs(src).toString();
return sub(div(new DataType(divNum), dest), new DataType("00000000000000000000000000000000"));
} else {
// 如果被除数为负,则取反被除数再递归调用
divedNum = abs(dest).toString();
DataType result = sub(div(src, new DataType(divedNum)), new DataType("00000000000000000000000000000000"));
if (!result.toString().contains("1")) {
// 如果结果为0,则说明不够除,将余数置为被除数
remainderReg = dest;
return result;
}
// 因为div运算的结果是都为正数的情况,所以要把结果取反
remainderReg = sub(remainderReg, new DataType("00000000000000000000000000000000"));
return result;
}
} else {
// 相同符号的情况下
if (signDivNum == '1') {
// 如果两个数都为负
divNum = abs(src).toString();
divedNum = abs(dest).toString();
// 同时取反,送进div
DataType result = div(new DataType(divNum), new DataType(divedNum));
remainderReg = sub(remainderReg, new DataType("00000000000000000000000000000000"));
// 虽然result不用变,但是余数要记得取反
return result;
}
}

StringBuilder quotientRemain;


quotientRemain = new StringBuilder("00000000000000000000000000000000" + divedNum);
// 补到64位,表示余数(32位) + 商(32位)

quotientRemain = new StringBuilder(sub(src, new DataType(quotientRemain.substring(0, 32))).toString() + quotientRemain.substring(32));
// 初始化完成,因为符号恒相同

signReminer = quotientRemain.charAt(0);


for (int i = 0; i < 32; i++) {
quotientRemain = new StringBuilder(quotientRemain.substring(1));
// 乘二
if (signReminer == signDivNum) {
// 如果余数的符号和除数的符号相同,则商补1
// 并使余数减去除数
quotientRemain = new StringBuilder(sub(src, new DataType(quotientRemain.substring(0, 32))).toString() + quotientRemain.substring(32));
// 余数为前32位,所以裁剪出来运算后再将原来后面32位的商恢复
} else {
quotientRemain = new StringBuilder(add(src, new DataType(quotientRemain.substring(0, 32))).toString() + quotientRemain.substring(32));
}
signReminer = quotientRemain.charAt(0);
if (signReminer == signDivNum) {
quotientRemain.append("1");
} else {
quotientRemain.append("0");
}
}

signReminer = quotientRemain.charAt(0);
String quotient = quotientRemain.substring(32);
// 分离出除数
remainderReg = new DataType(quotientRemain.substring(0, 32));

if (signDivedNum != signReminer) {
remainderReg = add(remainderReg, src);
}

if (!quotient.contains("1")) {
// 如果商为0,则将余数置为被除数(特判)
remainderReg = dest;
}

return new DataType(quotient);
}

除法部分注意事项:

  • 最开始的特判应将除数为0抛出异常放置最前面

  • 抛出错误语句

  • ```java
    throw new ArithmeticException();

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162

    - 偷懒递归用逻辑:

    - 如果符号不相同
    - 如果除数为负
    - 将除数取反
    - 将结果得到的商取反
    - 如果被除数为负
    - 将被除数取反
    - 将结果得到的商取反
    - 将余数取反
    - 如果符号相同
    - 如果两个都为负
    - 将两个都取反
    - 将余数取反

    - 余数的符号跟随被除数

    ## FPU

    ### mul()

    ```java
    /**
    * 浮点数乘法
    * dest * src
    * @param src
    * @param dest
    * @return
    */
    public DataType mul(DataType src, DataType dest) {
    String plussedNum = dest.toString();
    //被乘数;
    String plusNum = src.toString();
    //乘数;

    if (plussedNum.matches(IEEE754Float.NaN_Regular) || plusNum.matches(IEEE754Float.NaN_Regular)) {
    return new DataType(IEEE754Float.NaN);
    }
    //非数字检查;

    if (cornerCheck(mulCorner, plussedNum, plusNum) != null) {
    return new DataType(Objects.requireNonNull(cornerCheck(mulCorner, plussedNum, plusNum)));
    }
    //边界值判断;

    String signPlussedNum = plussedNum.substring(0,1);
    //被加数符号位;

    StringBuilder exponentPlussedNum = new StringBuilder(plussedNum.substring(1, 9));
    //被加数阶码;

    StringBuilder suffixPlussedNum = new StringBuilder(plussedNum.substring(9));
    //被加数尾数(未添加);

    if (exponentPlussedNum.indexOf("1") != -1) {
    suffixPlussedNum.insert(0, "1");
    } else {
    suffixPlussedNum.insert(0, "0");
    exponentPlussedNum.setCharAt(7, '1');
    }
    // 若为规格化数,则补隐藏位
    // 若为非规格化数,则补影藏位为0并将阶码加

    suffixPlussedNum.append("000");
    // 与加法部分相同;

    String signPlusNum = plusNum.substring(0,1);
    //加数符号位;

    StringBuilder exponentPlusNum = new StringBuilder(plusNum.substring(1, 9));
    //加数阶码;

    StringBuilder suffixPlusNum = new StringBuilder(plusNum.substring(9));
    //加数尾数(未添加);

    if (exponentPlusNum.indexOf("1") != -1) {
    suffixPlusNum.insert(0, "1");
    } else {
    suffixPlusNum.insert(0, "0");
    exponentPlusNum.setCharAt(7, '1');
    }//若为规格化数则补1,否则补0;
    suffixPlusNum.append("000");

    //阶码相加;
    int exponentResultNum = Integer.parseInt(exponentPlusNum.toString(), 2) + Integer.parseInt(exponentPlussedNum.toString(), 2);

    exponentResultNum -= 127;
    //减去多余的偏置常数;
    for (int i = suffixPlusNum.length(); i < 32; i++) {
    suffixPlusNum.insert(0, "0");
    suffixPlussedNum.insert(0, "0");
    // 将尾数补齐为32位(方便调用已有的整数乘法)
    }
    StringBuffer suffixResult = new StringBuffer(mul(suffixPlusNum.toString(), suffixPlussedNum.toString()));
    suffixResult = new StringBuffer(suffixResult.substring(10));

    //尾数乘法操作结束;
    //temp应为54位;
    //裁剪高54位作为结果;

    exponentResultNum++;
    //修正多余隐藏位;
    //由于两个操作数的隐藏位均为1位,所以乘积的隐藏位为2位。为了方便后续操作,需要通过阶码加1的方式来间接实现小数点的左移,修正这个误差,以保证尾数的隐藏位均为1位。

    char signResult;
    if (signPlussedNum.equals(signPlusNum)) {
    signResult = '0';
    } else {
    signResult = '1';
    }
    //符号位计算;

    while (suffixResult.charAt(0) == '0' && exponentResultNum > 0) {
    //隐藏位等于0且阶码大于0;
    suffixResult.append("0");
    suffixResult.deleteCharAt(0);
    //尾数左移;

    exponentResultNum--;
    //阶码减一;
    }

    while (suffixResult.substring(0, 28).contains("1") && exponentResultNum < 0) {
    //尾数前27位不全为0且阶码小于0;
    suffixResult = new StringBuffer(rightShift(suffixResult.toString(), 1));
    //尾数右移;

    //exponentResult = exponentAdd(exponentResult);
    exponentResultNum++;
    //阶码加一;
    }

    if (exponentResultNum > 254) {
    if (signResult == '1') {
    return new DataType(IEEE754Float.N_INF);
    } else {
    return new DataType(IEEE754Float.P_INF);
    }//阶码上溢,返回正负无穷;
    } else if (exponentResultNum < 0) {
    if (signResult == '0') {
    return new DataType(IEEE754Float.P_ZERO);
    } else {
    return new DataType(IEEE754Float.N_ZERO);
    }
    //阶码下溢,按照符号位返回正0或负0;
    } else if (exponentResultNum == 0) {
    suffixResult = new StringBuffer(rightShift(suffixResult.toString(), 1));
    //阶码等于0,尾数右移一次为非规格化数;
    }
    //规格化操作完成;

    StringBuilder exponentResult = new StringBuilder(Integer.toBinaryString(exponentResultNum));
    while (exponentResult.length() > 8) {
    exponentResult.deleteCharAt(0);
    }
    while (exponentResult.length() < 8) {
    exponentResult.insert(0, "0");
    }
    //阶码处理操作,将数字转为二进制串并规范长度;
    return new DataType(round(signResult, exponentResult.toString(), suffixResult.toString()));
    }

代码规格化部分逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while (隐藏位 == 0 && 阶码 > 0) {
尾数左移,阶码减1; // 左规
}
while (尾数前27位不全为0 && 阶码 < 0) {
尾数右移,阶码加1; // 右规
}

if (阶码上溢) {
将结果置为无穷;
} else if (阶码下溢) {
将结果置为0;
} else if(阶码 == 0) {
尾数右移一次化为非规格化数;
} else {
此时阶码正常,无需任何操作;
}

div()

与mul相比,除阶码加法改为减法、尾数由乘法改为除法以外无区别

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* compute the float mul of dest / src
*/
public DataType div(DataType src, DataType dest) {
String plussedNum = dest.toString();
//被乘数;
String plusNum = src.toString();
//乘数;

if (plussedNum.matches(IEEE754Float.NaN_Regular) || plusNum.matches(IEEE754Float.NaN_Regular)) {
return new DataType(IEEE754Float.NaN);
}
//非数字检查;

if (cornerCheck(divCorner, plussedNum, plusNum) != null) {
return new DataType(Objects.requireNonNull(cornerCheck(divCorner, plussedNum, plusNum)));
}
//边界值判断;

String signPlussedNum = plussedNum.substring(0,1);
//被加数符号位;

StringBuilder exponentPlussedNum = new StringBuilder(plussedNum.substring(1, 9));
//被加数阶码;

StringBuilder suffixPlussedNum = new StringBuilder(plussedNum.substring(9));
//被加数尾数(未添加);

if (exponentPlussedNum.indexOf("1") != -1) {
suffixPlussedNum.insert(0, "1");
} else {
suffixPlussedNum.insert(0, "0");
exponentPlussedNum.setCharAt(7, '1');
}//若为规格化数则补1,否则补0;
suffixPlussedNum.append("000");

String signPlusNum = plusNum.substring(0,1);
//加数符号位;

StringBuilder exponentPlusNum = new StringBuilder(plusNum.substring(1, 9));
//加数阶码;

StringBuilder suffixPlusNum = new StringBuilder(plusNum.substring(9));
//加数尾数(未添加);

if (exponentPlusNum.indexOf("1") != -1) {
suffixPlusNum.insert(0, "1");
} else {
suffixPlusNum.insert(0, "0");
exponentPlusNum.setCharAt(7, '1');
}//若为规格化数则补1,否则补0;
suffixPlusNum.append("000");

int exponentNum = Integer.parseInt(exponentPlussedNum.toString(), 2) - Integer.parseInt(exponentPlusNum.toString(), 2) + 127;
//计算阶码;

for (int i = suffixPlusNum.length(); i < 32; i++) {
suffixPlusNum.insert(0, "0");
suffixPlussedNum.insert(0, "0");
}
//补齐为32位;

StringBuilder suffixResult = new StringBuilder(div(suffixPlusNum.toString(), suffixPlussedNum.toString()));
suffixResult = new StringBuilder(suffixResult.substring(0, 27));

char signResult;
if (signPlussedNum.equals(signPlusNum)) {
signResult = '0';
} else {
signResult = '1';
}
//符号位计算;

//while (suffixResult.charAt(0) == '0' && exponentResult.charAt(0) == '0' && exponentResult.indexOf("1") != -1) {
while (suffixResult.charAt(0) == '0' && exponentNum > 0) {
//隐藏位等于0且阶码大于0;
suffixResult.append("0");
suffixResult.deleteCharAt(0);
//尾数左移;
//exponentResult = exponentSub(exponentResult);
exponentNum--;
//阶码减一;
}

while (suffixResult.substring(0, 27).contains("1") && exponentNum < 0) {
//尾数前27位不全为0且阶码小于0;
suffixResult = new StringBuilder(rightShift(suffixResult.toString(), 1));
//尾数右移;

//exponentResult = exponentAdd(exponentResult);
exponentNum++;
//阶码加一;
}

if (exponentNum > 254) {
if (signResult == '1') {
return new DataType(IEEE754Float.N_INF);
} else {
return new DataType(IEEE754Float.P_INF);
}//阶码上溢,返回正负无穷;
} else if (exponentNum < 0) {
if (signResult == '0') {
return new DataType(IEEE754Float.P_ZERO);
} else {
return new DataType(IEEE754Float.N_ZERO);
}
//阶码下溢,将结果置位正零;
} else if (exponentNum == 0) {
suffixResult = new StringBuilder(rightShift(suffixResult.toString(), 1));
//阶码等于0,尾数右移一次为非规格化数;
}
//规格化操作完成;
StringBuilder exponentResult = new StringBuilder(Integer.toBinaryString(exponentNum));
while (exponentResult.length() > 8) {
exponentResult.deleteCharAt(0);
}
while (exponentResult.length() < 8) {
exponentResult.insert(0, "0");
}

//if (round(signResult, exponentResult.toString(), suffixResult.toString()).equals(IEEE754Float.N_ZERO)) {
// return new DataType(IEEE754Float.P_ZERO);
//}
return new DataType(round(signResult, exponentResult.toString(), suffixResult.toString()));
}

add()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
* compute the float add of (dest + src)
*/
public DataType add(DataType src, DataType dest) {
String plussedNum = dest.toString();
//被加数,即第一个数;
String plusNum = src.toString();
//加数,即第二个数;

if (plussedNum.matches(IEEE754Float.NaN_Regular) || plusNum.matches(IEEE754Float.NaN_Regular))
{
return new DataType(IEEE754Float.NaN);
}
//非数字检查;

if (cornerCheck(addCorner, plussedNum, plusNum) != null) {
return new DataType(Objects.requireNonNull(cornerCheck(addCorner, plussedNum, plusNum)));
}
//边界值判断;

if (plussedNum.equals(IEEE754Float.P_ZERO) || plussedNum.equals(IEEE754Float.N_ZERO)) {
return src;
}
if (plusNum.equals(IEEE754Float.P_ZERO) || plusNum.equals(IEEE754Float.N_ZERO)) {
return dest;
}
//偷懒;

String signPlussedNum = plussedNum.substring(0,1);
//被加数符号位;

StringBuilder exponentPlussedNum = new StringBuilder(plussedNum.substring(1, 9));
//被加数阶码;

StringBuilder suffixPlussedNum = new StringBuilder(plussedNum.substring(9));
//被加数尾数(未添加);

if (exponentPlussedNum.indexOf("1") != -1) {
// 若阶码部分全为0,则表示为非规格化数
suffixPlussedNum.insert(0, "1");
} else {
suffixPlussedNum.insert(0, "0");
//若为规格化数则尾数补1,否则补0;
exponentPlussedNum.setCharAt(7, '1');
// 阶码加1(方便对阶)
}
suffixPlussedNum.append("000");
// 保护位;

String signPlusNum = plusNum.substring(0,1);
//加数符号位;

StringBuilder exponentPlusNum = new StringBuilder(plusNum.substring(1, 9));
//加数阶码;

StringBuilder suffixPlusNum = new StringBuilder(plusNum.substring(9));
//加数尾数(未添加);

if (exponentPlusNum.indexOf("1") != -1) {
suffixPlusNum.insert(0, "1");
} else {
suffixPlusNum.insert(0, "0");
exponentPlusNum.setCharAt(7, '1');
}//若为规格化数则补1,否则补0;
suffixPlusNum.append("000");



boolean plussedLargerPlus = true;
//表示被加数阶码是否大于加数;

for (int i = 0; i < 8; i++) {
if (exponentPlussedNum.charAt(i) != exponentPlusNum.charAt(i)) {
if (exponentPlussedNum.charAt(i) == '1') {
break;
} else {
plussedLargerPlus = false;
break;
}
}
}
//判断哪个阶码大;

if (plussedLargerPlus) {
while (!exponentPlussedNum.toString().equals(exponentPlusNum.toString())) {
exponentPlusNum = exponentAdd(exponentPlusNum);
suffixPlusNum = new StringBuilder(rightShift(suffixPlusNum.toString(), 1));
}
} else {
while (!exponentPlussedNum.toString().equals(exponentPlusNum.toString())) {
exponentPlussedNum = exponentAdd(exponentPlussedNum);
suffixPlussedNum = new StringBuilder(rightShift(suffixPlussedNum.toString(), 1));
}
}
//对阶操作;

if (suffixPlusNum.indexOf("1") == -1) {
return dest;
}
if (suffixPlussedNum.indexOf("1") == -1) {
return src;
}
//偷懒;


StringBuilder suffixResult;
StringBuilder exponentResult = exponentPlussedNum;
if (signPlussedNum.equals(signPlusNum)) {
suffixResult = add(suffixPlussedNum, suffixPlusNum, signPlussedNum);
} else {
suffixResult = sub(suffixPlussedNum, suffixPlusNum, signPlussedNum);
}
signPlussedNum = String.valueOf(suffixResult.charAt(suffixResult.length() - 1));
suffixResult = new StringBuilder(suffixResult.substring(0, suffixResult.length() - 1));

//尾数相加操作;

if (suffixResult.length() > 27) {
while (suffixResult.length() != 27) {
suffixResult.deleteCharAt(suffixResult.length()-1);
//尾码右移;
exponentResult = exponentAdd(exponentResult);
//阶码加一;
if (exponentResult.indexOf("0") == -1) {
if ("1".equals(signPlussedNum)) {
return new DataType(IEEE754Float.N_INF);
} else {
return new DataType(IEEE754Float.P_INF);
}
}
//偷懒;
}
}
//如果尾数大于27位,则应该将尾数右移并将阶码加1;

if (suffixResult.length() < 27) {
while (suffixResult.length() != 27) {
suffixResult.append("0");
exponentResult = exponentSub(exponentResult);

if (exponentResult.indexOf("1") == -1) {
suffixResult = new StringBuilder(rightShift(suffixResult.toString(), 1));
for (int i = suffixResult.length(); i < 27; i++) {
suffixResult.insert(0, '0');
}
String temp = (signPlussedNum + exponentResult.toString() + suffixResult.substring(1, 24));
if (temp.equals(IEEE754Float.N_ZERO)) {
signPlussedNum = "0";
}
return new DataType(round(signPlussedNum.charAt(0), exponentResult.toString(), suffixResult.toString()));
}
}
}

while (suffixResult.charAt(0) != '1') {
if ("00000001".equals(exponentResult.toString()) && suffixResult.charAt(0) == '0') {
exponentResult = exponentSub(exponentResult);
break;
}
suffixResult.append("0");
suffixResult.deleteCharAt(0);
//左移;
exponentResult = exponentSub(exponentResult);
//阶码减一;
}

String temp = (signPlussedNum + exponentResult.toString() + suffixResult.substring(1, 24));
if (temp.equals(IEEE754Float.N_ZERO)) {
signPlussedNum = "0";
}

return new DataType(round(signPlussedNum.charAt(0), exponentResult.toString(), suffixResult.toString()));
}

sub()

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
/**
* compute the float add of (dest - src)
*/
public DataType sub(DataType src, DataType dest) {
StringBuilder srcNum = new StringBuilder(src.toString());
if (srcNum.charAt(0) == '1') {
srcNum.setCharAt(0, '0');
} else {
srcNum.setCharAt(0, '1');
}
src = new DataType(srcNum.toString());

String plussedNum = dest.toString();
String plusNum = src.toString();

if (plussedNum.matches(IEEE754Float.NaN_Regular) || plusNum.matches(IEEE754Float.NaN_Regular))
{
return new DataType(IEEE754Float.NaN);
}
//非数字检查;

if (cornerCheck(subCorner, plussedNum, plusNum) != null) {
return new DataType(Objects.requireNonNull(cornerCheck(subCorner, plussedNum, plusNum)));
}
//边界值判断;
return add(src, dest);
}

NBCDU

add()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	int c = 0;
/**
* @param src A 32-bits NBCD String
* @param dest A 32-bits NBCD String
* @return dest + src
*/
DataType add(DataType src, DataType dest) {
c = 0;
int len = 32;
String plussedNum = dest.toString();
String plusNum = src.toString();

if (!plussedNum.substring(4).contains("1")) {
return src;
}

if (!plusNum.substring(4).contains("1")) {
return dest;
}
// 偷懒

boolean ifSub = false;
String sign = "1100";
String signPlussedNum = plussedNum.substring(0, 4);
String signPlusNum = plusNum.substring(0, 4);

plussedNum = plussedNum.substring(4);
plusNum = plusNum.substring(4);

if (signPlussedNum.equals(signPlusNum)) {
// 若两数符号相同:
if ("1101".equals(signPlusNum)) {
// 若两数符号都为负
// 将符号位置为负,正常运算
sign = "1101";
}
} else {
ifSub = true;
// 减法标记
if ("1101".equals(signPlusNum)) {
plusNum = invert(plusNum);
/
}
if ("1101".equals(signPlussedNum)) {
plussedNum = invert(plussedNum);
}
}
//判断是加法还是减法;

StringBuilder result = new StringBuilder();
for (int i = len - 8; i >= 0; i-= 4) {
int temp = Integer.parseInt(plussedNum.substring(i, i + 4), 2) + Integer.parseInt(plusNum.substring(i, i + 4), 2) + c;
c = 0;
//重置进位;
if (temp > 9) {
temp = temp + 6 - 16;
c++;
}
String tempStr = Integer.toBinaryString(temp);
tempStr = repeat('0', 4 - tempStr.length()) + tempStr;
result.insert(0, tempStr);
}

if (ifSub) {
if (c == 0) {
result = new StringBuilder(invert(result.toString()));
if ("1101".equals(sign)) {
sign = "1100";
} else {
sign = "1101";
}
}
} else {
if (c == 1) {
result.insert(0, "0001");
}
}

if (result.length() > 28) {
while (result.length() > 28) {
result.deleteCharAt(0);
}
}
result.insert(0, repeat('0', len - 4 - result.length()));
c = 0;
StringBuilder res = new StringBuilder();
for (int i = len - 8; i >= 0; i-= 4) {
int temp = Integer.parseInt(result.substring(i, i + 4), 2) + c;
c = 0;
if (temp > 9) {
temp = temp + 6 - 16;
c++;
}
String tempStr = Integer.toBinaryString(temp);
tempStr = repeat('0', 4 - tempStr.length()) + tempStr;
res.insert(0, tempStr);
}
res.insert(0, sign);
if (!res.substring(4).contains("1")) {
res.setCharAt(3, '0');
}
return new DataType(res.toString());
}

sub()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/***
*
* @param src A 32-bits NBCD String
* @param dest A 32-bits NBCD String
* @return dest - src
*/
DataType sub(DataType src, DataType dest) {
StringBuilder srcBuilder = new StringBuilder(src.toString());
if (!srcBuilder.substring(4).contains("1")) {
return add(src, dest);
}
if (srcBuilder.charAt(3) == '0') {
srcBuilder.setCharAt(3, '1');
} else {
srcBuilder.setCharAt(3, '0');
}
//改变符号;
return add(new DataType(srcBuilder.toString()), dest);
}

String oneAdder(String src) {
StringBuilder result = new StringBuilder(src);
int len = result.length();
if (result.charAt(len - 1) == '0') {
result.setCharAt(len - 1, '1');
return result.toString();
} else {
for (int i = src.length() - 1; i >= 0; i--) {
if (result.charAt(i) == '0') {
result.setCharAt(i, '1');
return result.toString();
} else {
result.setCharAt(i, '0');
}
}
}
return result.toString();
}

String repeat(int n) {
String result = "";
for (int i = 0; i < n; i++) {
result += '0';
}
return result;
}


/**
* 对src进行NBCD补码运算;
*/
String invert(String src) {
HashMap<String, String> buma = new HashMap<>();
buma.put("0000", "1001");
buma.put("0001", "1000");
buma.put("0010", "0111");
buma.put("0011", "0110");
buma.put("0100", "0101");
buma.put("0101", "0100");
buma.put("0110", "0011");
buma.put("0111", "0010");
buma.put("1000", "0001");
buma.put("1001", "0000");
StringBuilder result = new StringBuilder();
for (int i = src.length(); i > 0; i -= 4) {
if (i == src.length()) {
String temp = buma.get(src.substring(i-4, i)).toString();
temp = oneAdder(temp);
result.insert(0, temp);
continue;
}
result.insert(0, buma.get(src.substring(i-4, i)));
}
return result.toString();
}

CRC

calculate()

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
43
44
45
46
47
48
49
50
51
/**
* CRC计算器
*
* @param data 数据流
* @param polynomial 多项式
* @return CheckCode
*/
public static char[] Calculate(char[] data, String polynomial) {
int dataLen = data.length;
int polyLen = polynomial.length();
char[] dataChar = new char[dataLen + polyLen - 1];

for (int i = 0; i < dataLen; i++) {
dataChar[i] = data[i];
}

for (int i = dataLen; i < dataChar.length; i++) {
dataChar[i] = '0';
}

ArrayList<Character> result = new ArrayList<>();
for (int j = 0; j < polyLen; j++) {

result.add(oplus(dataChar[j], '0'));
}

ArrayList<Character> temp = new ArrayList<>();
for (int i = 0; i < dataLen; i++) {
if (result.get(0) == polynomial.charAt(0)) {
for (int j = 1; j < polyLen; j++) {
temp.add(oplus(result.get(j), polynomial.charAt(j)));
}
} else {
for (int j = 1; j < polyLen; j++) {
temp.add(oplus(result.get(j), '0'));
}
}
if (i != dataLen - 1) {
temp.add(dataChar[i + polyLen]);
}

result = new ArrayList<>(temp);
temp.clear();
}

char[] resultChar = new char[result.size()];
for (int i = 0; i < resultChar.length; i++) {
resultChar[i] = result.get(i);
}
return resultChar;
}

check()

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* CRC校验器
*
* @param data 接收方接受的数据流
* @param polynomial 多项式
* @param CheckCode CheckCode
* @return 余数
*/
public static char[] Check ( char[] data, String polynomial,char[] CheckCode) {
int dataLen = data.length;
int polyLen = polynomial.length();
char[] dataChar = new char[dataLen + polyLen - 1];

for (int i = 0; i < dataLen; i++) {
dataChar[i] = data[i];
}

for (int i = 0; i < dataChar.length - dataLen; i++) {
dataChar[i + dataLen] = CheckCode[i];
}

ArrayList<Character> result = new ArrayList<>();
for (int j = 0; j < polyLen; j++) {
result.add(dataChar[j]);
}

ArrayList<Character> temp = new ArrayList<>();
for (int i = 0; i < dataLen; i++) {
if (result.get(0) == polynomial.charAt(0)) {
for (int j = 1; j < polyLen; j++) {
temp.add(oplus(result.get(j), polynomial.charAt(j)));
}
} else {
for (int j = 1; j < polyLen; j++) {
temp.add(oplus(result.get(j), '0'));
}
}
if (i != dataLen - 1) {
temp.add(dataChar[i + polyLen]);
}

result = new ArrayList<>(temp);
temp.clear();
}

char[] resultChar = new char[result.size()];
for (int i = 0; i < resultChar.length; i++) {
resultChar[i] = result.get(i);
}
return resultChar;
}

private static char oplus ( char a, char b){
if (a == b) {
return '0';
} else {
return '1';
}
}