浮点数加减乘除,模拟二进制加减乘除,位操作

浮点数的内存形式就不说了,就符号位,指数域,尾数域。
书本可以参考计算机体系结构
不多说,代码如下:


// float.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "string"
#include "iostream"
#include "iomanip"
#include "stack"
#include "queue"
#include "math.h"

using namespace std;

struct Myfloat
{
	bool sign;
	int enponential;
	int leave;
	Myfloat() { sign = 0; enponential = 0x00000000; leave = 0x00000000; };//两个构造函数
	Myfloat(bool sign, int enponential, int leave) :sign(sign), enponential(enponential), leave(leave) {};
};

class yusuan
{
public:
	yusuan();
	~yusuan();
	void get_string();//字符串输入
	void to_Myfloat(Myfloat&, string&);//将字符串先转换为十进制,再转换为二进制
	void to_Myfloat();//两次调用上一个函数
	double relieve(Myfloat);//用公式将浮点数还原
	static int to_right_one(int&);//右移一位,补0(其实没有必要)
	static int to_right_one(int&, int);//右移多位,补0
	static int to_left_one(int&);//左移一位,补0(其实没有必要)
	static int to_right_one_add_one(int&);//右移一位,补1
	static int to_left_one_add_one(int&);//左移一位,补1
	static int get_one_compare(int);//去1,第n位为0,其他为1
	static int onlyone_otherIsZero(int);//补1,第n位为1,其他为0
	static Myfloat add(Myfloat&, Myfloat&);//加法
	static Myfloat substruct(Myfloat&, Myfloat&);//减法
	static Myfloat multiply(Myfloat&, Myfloat&);//乘法
	static Myfloat divide(Myfloat&, Myfloat&);//除法

	Myfloat one;//第一个数
	Myfloat two;//第二个数
	string s_one;//字符串1
	string s_two;//字符串2
};

int yusuan::onlyone_otherIsZero(int n)
{
	int  ret = 0x80000000;
	n--;
	while (n--)
	{
		to_right_one(ret);
	}
	return ret;
}

Myfloat yusuan::divide(Myfloat& one_divide, Myfloat& two_divide)//二进制除法,不断地减,直到到23位
{
	Myfloat ret;
	Myfloat t1(0, one_divide.enponential, one_divide.leave);
	Myfloat t2(0, two_divide.enponential, two_divide.leave);

	if (two_divide.enponential == 0x00000000 && two_divide.leave == 0x00000000)
	{
		cout << "被除数不能为0" << endl;
	}
	else
	{
		if (one_divide.sign && !two_divide.sign || !one_divide.sign&&two_divide.sign)
		{
			ret = divide(t1, t2);
			ret.sign = 1;
		}
		else
		{
			ret.sign = 0;
			ret.enponential = t1.enponential - t2.enponential + 127 + 2;
			to_right_one_add_one(t1.leave);
			to_right_one_add_one(t2.leave);
			to_right_one(t1.leave);
			to_right_one(t2.leave);
			unsigned int leave1 = (unsigned int)t1.leave;
			unsigned int leave2 = (unsigned int)t2.leave;
			if (leave1 == leave2)
			{
				ret.leave = 0x00000000;
			}
			else
			{
				queue<bool> q;
				while (q.size() <= 24)
				{
					if (leave1 == leave2)
					{
						q.push(1);
						break;
					}
					else if (leave1 > leave2)
					{
						q.push(1);
						leave1 -= leave2;
					}
					else
					{
						q.push(0);
					}
					leave1 <<= 1;
					leave1 &= 0xfffffffe;
				}
				while (q.front() == 0 && !q.empty())
				{
					ret.enponential--;
					q.pop();
				}
				if (!q.empty())
				{
					q.pop();
					int temp = 0x80000000;
					while (!q.empty())
					{
						if (q.front())
						{
							ret.leave |= temp;
						}
						q.pop();
						to_right_one(temp);
					}
				}
				else
				{
					cout << "Something wrong!" << endl;
				}
			}
			ret.enponential -= 2;
		}
	}
	return ret;
}

int yusuan::to_right_one(int& temp, int n)
{
	while (n--)
	{
		to_right_one(temp);
	}
	return temp;
}

int yusuan::get_one_compare(int n)
{
	int ret = 0x7fffffff;
	n--;
	while (n--)
	{
		to_right_one_add_one(n);
	}
	return ret;
}

Myfloat yusuan::multiply(Myfloat& one_multiply, Myfloat& two_multiply)//二进制乘法
{
	Myfloat ret;
	Myfloat t1(0, one_multiply.enponential, one_multiply.leave);
	Myfloat t2(0, two_multiply.enponential, two_multiply.leave);
	int weight = 0;

	if ((!one_multiply.sign&&two_multiply.sign) || (one_multiply.sign && !two_multiply.sign))
	{
		ret = multiply(t1, t2);
		ret.sign = 1;
	}
	else
	{
		ret.sign = 0;
		ret.enponential = t1.enponential + t2.enponential - 127 + 2;
		to_right_one_add_one(t1.leave);
		to_right_one_add_one(t2.leave);
		unsigned long long leave1 = 0;
		leave1 |= (unsigned long long)t1.leave;
		leave1 &= 0x00000000ffffffff;
		unsigned long long leave2 = 0;
		leave2 |= (unsigned long long)t2.leave;
		leave2 &= 0x00000000ffffffff;
		unsigned long long add = leave1 << 23;
		unsigned long long compare = 0x0000000000000100;
		for (int i = 0; i < 24; i++)
		{
			if (compare&leave2)
			{
				leave1 += add;
			}
			leave1 >>= 1;
			leave2 >>= 1;
		}
		leave1 <<= 1;
		compare = 0x0080000000000000;
		add = 0x80000000;
		for (int i = 0; i < 24; i++)
		{
			if (compare&leave1)
			{
				ret.leave |= add;
			}
			compare >>= 1;
			add >>= 1;
		}
		for (int i = 0; i < 23; i++)
		{
			if (ret.leave & 0x80000000)
			{
				ret.enponential--;
				to_left_one(ret.leave);
				break;
			}
			ret.enponential--;
			to_left_one(ret.leave);
		}
	}

	return ret;
}

int yusuan::to_right_one_add_one(int& temp)
{
	temp >>= 1;
	temp |= 0x80000000;
	return temp;
}


int yusuan::to_left_one_add_one(int& temp)
{
	temp <<= 1;
	temp |= 0x00000001;
	return temp;
}

Myfloat yusuan::substruct(Myfloat& one_substruct, Myfloat& two_substruct)
{
	Myfloat ret;

	if (one_substruct.sign && !two_substruct.sign)//负减正
	{
		ret = two_substruct;
		ret.sign = 1;
		return add(one_substruct, ret);
	}
	else if (!one_substruct.sign && two_substruct.sign)//正减负
	{
		ret = two_substruct;
		ret.sign = 0;
		return add(one_substruct, ret);
	}
	else if (one_substruct.sign && two_substruct.sign)//负减负
	{
		ret = two_substruct;
		ret.sign = 0;
		Myfloat change(0, one_substruct.enponential, one_substruct.leave);
		return substruct(ret, change);
	}
	else//正减正
	{
		ret.sign = one_substruct.sign;
		int diffierent_of_enponential;
		int one_of_enponential = one_substruct.enponential - 127;
		int two_of_enponential = two_substruct.enponential - 127;

		diffierent_of_enponential = one_of_enponential - two_of_enponential;
		if (diffierent_of_enponential > 0)
		{
			Myfloat move_binary(two_substruct.sign, two_substruct.enponential, two_substruct.leave);
			to_right_one_add_one(move_binary.leave);
			move_binary.enponential++;
			diffierent_of_enponential--;
			for (int i = 0; i < diffierent_of_enponential; i++)
			{
				move_binary.enponential++;
				to_right_one(move_binary.leave);
			}
			ret.sign = one_substruct.sign;
			to_right_one_add_one(one_substruct.leave);
			ret.enponential = one_substruct.enponential + 1;
			to_right_one(move_binary.leave);
			ret.leave = one_substruct.leave - move_binary.leave;
			to_left_one(one_substruct.leave);
		}
		else if (diffierent_of_enponential < 0)//可以调换位置,再调用substruct,变符号
		{
			Myfloat move_binary(one_substruct.sign, one_substruct.enponential, one_substruct.leave);
			to_right_one_add_one(move_binary.leave);
			move_binary.enponential++;
			diffierent_of_enponential++;
			for (int i = 0; i < (-diffierent_of_enponential); i++)
			{
				move_binary.enponential++;
				to_right_one(move_binary.leave);
			}
			ret.sign = 1;
			to_right_one_add_one(two_substruct.leave);
			ret.enponential = two_substruct.enponential + 1;
			to_right_one(move_binary.leave);
			ret.leave = two_substruct.leave - move_binary.leave;
			to_left_one(two_substruct.leave);
		}
		else
		{
			ret.enponential = one_substruct.enponential;
			to_right_one_add_one(one_substruct.leave);
			to_right_one_add_one(two_substruct.leave);
			ret.enponential++;
			if (one_substruct.leave>two_substruct.leave)
			{
				ret.leave = one_substruct.leave - two_substruct.leave;
			}
			else
			{
				ret.leave = two_substruct.leave - one_substruct.leave;
				ret.sign = 1;
			}
			to_left_one(one_substruct.leave);
			to_left_one(two_substruct.leave);
		}
		for (int i = 0; i < 23; i++)
		{
			if (ret.leave & 0x80000000)
			{
				ret.enponential--;
				to_left_one(ret.leave);
				break;
			}
			ret.enponential--;
			to_left_one(ret.leave);
		}
	}

	return ret;
}

Myfloat yusuan::add(Myfloat& one_add, Myfloat& two_add)
{
	Myfloat ret;

	if (one_add.sign && !two_add.sign)//负加正
	{
		ret = one_add;
		ret.sign = 0;
		return substruct(two_add, ret);
	}
	else if (!one_add.sign && two_add.sign)//正加负
	{
		ret = two_add;
		ret.sign = 0;
		return substruct(one_add, ret);
	}
	else if (one_add.sign && two_add.sign)//负加负
	{
		ret = one_add;
		ret.sign = 0;
		Myfloat change(0, two_add.enponential, two_add.leave);
		ret = add(ret, change);
		ret.sign = 1;
		return ret;
	}
	else
	{
		int diffierent_of_enponential;

		ret.sign = one_add.sign;

		int one_of_enponential = one_add.enponential - 127;
		int two_of_enponential = two_add.enponential - 127;

		diffierent_of_enponential = one_of_enponential - two_of_enponential;
		if (diffierent_of_enponential > 0)
		{
			Myfloat move_binary(two_add.sign, two_add.enponential, two_add.leave);
			to_right_one_add_one(move_binary.leave);
			move_binary.enponential++;
			diffierent_of_enponential--;
			for (int i = 0; i < diffierent_of_enponential; i++)
			{
				move_binary.enponential++;
				to_right_one(move_binary.leave);
			}
			ret.enponential = one_add.enponential + 2;
			to_right_one_add_one(one_add.leave);
			to_right_one(move_binary.leave);
			ret.leave = to_right_one(one_add.leave) + to_right_one(move_binary.leave);
			to_left_one(one_add.leave);
			to_left_one(one_add.leave);
		}
		else if (diffierent_of_enponential < 0)//可以one和two换位置,用上面的计算
		{
			Myfloat move_binary(one_add.sign, one_add.enponential, one_add.leave);
			to_right_one_add_one(move_binary.leave);
			move_binary.enponential++;
			diffierent_of_enponential++;
			for (int i = 0; i < (-diffierent_of_enponential); i++)
			{
				move_binary.enponential++;
				to_right_one(move_binary.leave);
			}
			ret.enponential = two_add.enponential + 2;
			to_right_one_add_one(two_add.leave);
			to_right_one(move_binary.leave);
			ret.leave = to_right_one(two_add.leave) + to_right_one(move_binary.leave);
			to_left_one(two_add.leave);
			to_left_one(two_add.leave);
		}
		else
		{
			ret.enponential = one_add.enponential + 2;
			to_right_one_add_one(one_add.leave), to_right_one_add_one(two_add.leave);
			ret.leave = to_right_one(one_add.leave) + to_right_one(two_add.leave);
			to_left_one(one_add.leave);
			to_left_one(two_add.leave);
			to_left_one(one_add.leave);
			to_left_one(two_add.leave);
		}
		for (int i = 0; i < 23; i++)
		{
			if (ret.leave & 0x80000000)
			{
				ret.enponential--;
				to_left_one(ret.leave);
				break;
			}
			ret.enponential--;
			to_left_one(ret.leave);
		}
	}
	return ret;
}

double yusuan::relieve(Myfloat f)//不要传引用,传值
{
	double ret = 1;
	int compare = 0x80000000;

	if (f.enponential == 0x00000000 && f.leave == 0x00000000)return 0;

	int enponential = f.enponential - 127;

	ret *= pow(2, enponential--);
	for (int i = 0; i < 32; i++)
	{
		if (compare&f.leave)
		{
			ret += pow(2, enponential);
		}
		enponential--;
		to_right_one(compare);
	}
	return f.sign ? -ret : ret;
}

int yusuan::to_right_one(int& temp)
{
	temp >>= 1;
	temp &= 0x7fffffff;
	return temp;
}

int yusuan::to_left_one(int& temp)
{
	temp <<= 1;
	temp &= 0xfffffffe;
	return temp;
}

void yusuan::to_Myfloat()
{
	to_Myfloat(one, s_one);
	to_Myfloat(two, s_two);
}

void yusuan::to_Myfloat(Myfloat& f, string &s)
{
	char point;
	stack<bool> t;
	int temp = 0;

	point = (char)s.find('.');
	if (s.at(0) == '0' && point == string::npos)
	{
		f.enponential = 0x00000000;
		f.leave = 0x00000000;
		return;
	}
	if (s.at(0) != '-')
	{
		f.sign = 0;
		if (point == string::npos)//整数
		{
			for (int i = 0; i < s.size(); i++)//
			{
				temp = temp * 10 + s.at(i) - '0';
			}
			while (temp != 0)
			{
				t.push(temp % 2);
				temp /= 2;
			}
			f.enponential = t.size();//指数
			temp = 0x80000000;
			t.pop();
			for (int i = 0; !t.empty(); i++)
			{
				if (t.top())
				{
					f.leave |= temp;
				}
				t.pop();
				to_right_one(temp);
			}
		}
		else
		{
			queue<bool> q;
			int compare = 0;
			for (int i = 0; i < point; i++)
			{
				temp = temp * 10 + s.at(i) - '0';
			}
			while (temp != 0)
			{
				t.push(temp % 2);
				temp /= 2;
			}
			f.enponential = t.size();//未调整指数
			for (int i = 0; i < s.size() - point - 1; i++)
			{
				temp = temp * 10 + s.at(point + 1 + i) - '0';//将小数string化为整数乘2,不用float
				compare = i + 1;//记录位数
			}
			compare = (int)pow(10, compare);
			for (int j = 0; j < 23; j++)//尾部
			{
				temp *= 2;
				if (temp == compare)
				{
					q.push(1);
					break;
				}
				else if (temp > compare)
				{
					q.push(1);
					temp -= compare;
				}
				else
				{
					q.push(0);
				}
			}
			int i;
			temp = 0x80000000;
			if (f.enponential != 0)
			{
				t.pop();
				for (i = 0; !t.empty() && i <= 23; i++)
				{
					if (t.top())
					{
						f.leave |= temp;
					}
					t.pop();
					to_right_one(temp);
				}
			}
			else
			{
				while (q.front() != 1)
				{
					f.enponential--;
					q.pop();
				}
				q.pop();
				i = 0;
			}
			for (; !q.empty() && i <= 23; i++)
			{
				if (q.front())
				{
					f.leave |= temp;
				}
				to_right_one(temp);
				q.pop();
			}
		}
		f.enponential = f.enponential - 1 + 127;
	}
	else
	{
		s.erase(0, 1);
		to_Myfloat(f, s);
		f.sign = 1;
	}
}

void yusuan::get_string()
{
	cout << "请输入第一个数:";
	cin >> s_one;
	cout << "请输入第二个数:";
	cin >> s_two;
}

yusuan::yusuan()
{
}

yusuan::~yusuan()
{
}

int main()
{
	yusuan test;

	test.get_string();
	cout << test.s_one << "  " << test.s_two << endl;

	test.to_Myfloat();
	cout << test.one.sign << " " << test.one.enponential << " " << test.one.leave << endl;
	cout << fixed << setprecision(7) << test.relieve(test.one) << endl;
	cout << test.two.sign << " " << test.two.enponential << " " << test.two.leave << endl;
	cout << fixed << setprecision(7) << test.relieve(test.two) << endl;

	cout << fixed << setprecision(7) << "加法:" << test.relieve(test.add(test.one, test.two)) << endl;
	cout << fixed << setprecision(7) << "减法:" << test.relieve(test.substruct(test.one, test.two)) << endl;
	cout << fixed << setprecision(7) << "乘法:" << test.relieve(test.multiply(test.one, test.two)) << endl;
	cout << fixed << setprecision(7) << "除法:" << test.relieve(test.divide(test.one, test.two)) << endl;

	system("pause");

	return 0;
}


主要运用位操作(C语言),浮点数内存形式,二进制加减乘除(计算机体系结构)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值