模拟IEEE754的过程

#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
*/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值