#include <iostream>
using namespace std;
int carry; //CF
typedef struct FP{
string S; //1
string E; //8
string M; //23
string Guard, RoundUp, Safe;
} FPNumber;
int BitsZero(string a) {
for (auto c: a)
if (c == '1')
return false;
return true;
}
string BitsAdd(string a, string b);
int BitsToDecimal(string a);
void print(FPNumber a) {
cout << "符号: " << a.S << endl;
cout << "阶码: " << BitsToDecimal(a.E) - 127 << endl;
cout << "数符: " << a.M << endl;
cout << "G :" << ' ' << a.Guard << endl;
cout << "R :" << ' ' << a.RoundUp << endl;
cout << "S :" << ' ' << a.Safe << endl;
return;
}
FPNumber lShift(FPNumber a) {
string str = a.M + a.Guard + a.RoundUp + a.Safe;
while (str[0] != '1') {
a.E = BitsAdd(a.E, "11111111");
if (!carry) {
exit(1); //panic 溢出了
}
str = str.substr(1);
}
a.E = BitsAdd(a.E, "11111111");
if (!carry) {
exit(1); //panic 溢出了
}
str = str.substr(1);
while(str.size() < 26)
str += '0';
int bits = str.size() - 23;
if (bits > 0) {
a.Guard = str[23];
} else
a.Guard = "0";
if (bits > 1) {
a.RoundUp = str[23 + 1];
} else
a.RoundUp = "0";
if (bits > 2) {
int ok = 0;
for (int i = 23; i < str.length(); i ++)
if (str[i] == '1')
ok = 1;
a.Safe = ok + '0';
}
str = str.substr(0, 23);
a.M = str;
return a;
}
FPNumber rShift(FPNumber b, int bits) {
//对阶、右移,符号位不变;隐藏位1参与运算。
string r = "";
for (int i = 0; i < bits; i ++)
r += "0";
r += b.M;
cout << r << endl;
if (bits > 0) {
b.Guard = r[b.M.length()];
}
if (bits > 1) {
b.RoundUp = r[b.M.length() + 1];
}
if (bits > 2) {
int ok = 0;
for (int i = b.M.length(); i < r.length(); i ++)
if (r[i] == '1')
ok = 1;
b.Safe = ok + '0';
}
b.M = string(' ', 23);
for (int i = 0; i < 23; i ++)
b.M[i] = r[i];
return b;
}
string BitsAdd(string a, string b) {
carry = 0;
for (int i = b.length() - 1; i >= 0; i --) {
int A = a[i] - '0', B = b[i] - '0';
a[i] = (A + B + carry) % 2 + '0';
carry = (A + B + carry) / 2;
}
return a;
}
string BitsRev(string b) {
for (int i = 0; i < b.length(); i ++) {
if (b[i] == '0')
b[i] = '1';
else
b[i] = '0';
}
string one = "";
for (int i = 0; i < b.length() - 1; i ++)
one += '0';
one += '1';
b = BitsAdd(b, one);
return b;
}
string BitsSub(string a, string b) { //补码减法
b = BitsRev(b);
a = BitsAdd(b, a);
return a;
}
int BitsToDecimal(string a) {
reverse(a.begin(), a.end());
int ans = 0, exp = 1;
for (int i = 0; i < a.length(); i ++) {
int A = a[i] - '0';
ans = ans + exp * A;
exp <<= 1;
}
return ans;
}
FPNumber add(FPNumber a, FPNumber b) {
if (a.E > b.E) {
swap(a, b);
}
// 1. 对阶
FPNumber c = a; //小阶向大阶看齐; 只会右移.
c = rShift(c, BitsToDecimal(BitsSub(b.E, c.E))); //数码右移;
//对阶的时候不舍入!!
c.E = b.E; //阶码看齐.
print(c);
// 2. 尾数加减
// 尾数相加减的时候要把隐藏位加上. 也要带着GRS位.
string A = "1" + a.M + a.Guard + a.RoundUp + a.Safe;
string B = "1" + b.M + b.Guard + b.RoundUp + b.Safe;
//原码加法。
/*
比较两个操作数的符号;
对于加法,同和异差;
减法相反。
求和时,数值位相加,CF代表溢出;符号和被加数相同。
求差时,加数求补,进行加法运算。CF=1说明结果为正;否则为负。
最后要根据CF返回结果的真值(再次求补)。
*/
string C = "";
if (a.S != b.S) {
B = BitsRev(B);
C = BitsAdd(A, B);
if (carry) {
c.S = "0";
} else {
c.S = "1";
C = BitsRev(C);
}
carry = 0;
} else {
c.S = a.S;
C = BitsAdd(A, B);
}
if (BitsZero(C)) {
//带上隐藏位仍然是全0,机器零异常
exit(1); //panic;
}
// 3. 结果规格化
int ls = (C[0] == '0'); //如果隐藏位还是1的话,没必要左规了。
C = C.substr(1); //把隐藏位去掉..
c.M = C;
if (carry) { //溢出,右归. 原码加法只有同号会溢出.
c.E = BitsAdd(c.E, "00000001");
if (carry) {
exit(1); //panic
}
c = rShift(c, 1);
}
//左规。
if (ls)
c = lShift(c); //这个过程会溢出
print(c);
// 4. 尾数舍入
string RD = c.Guard + c.RoundUp + c.Safe;
if (RD >= "100") {
//这里要给c.M + 0.000...1,还要左规右规。
} else {
//truncate.
}
c.Guard = "0";
c.RoundUp = "0";
c.Safe = "0";
// 5. 判断溢出.
return c;
}
int main() {
FPNumber a = {"0", "01111111", "10000000000000000000000", "0", "0", "0"}; //1.5
FPNumber b = {"1", "01111111", "01000000000000000000000", "0", "0", "0"}; //1.25
add(a, b);
}
/*
100000000000000000001111000
100000000000000000000001000
1100000000000000000010000000
*/
模拟IEEE754的过程
最新推荐文章于 2024-11-09 21:51:15 发布