浮点数的内存形式就不说了,就符号位,指数域,尾数域。
书本可以参考计算机体系结构
不多说,代码如下:
// 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语言),浮点数内存形式,二进制加减乘除(计算机体系结构)。