高精度浮点类
前言
大家好,写代码也是一个上瘾的事情啊,刚刚结束了赫夫曼编码我就马不停蹄的开始着手算数编码了。不过在我研究了一下算数编码的原理过后,我发现如果只用C语言默认提供的float和double类型,去完成我们图像的算数编码好像有些困难。当我们不断的划分区间后,最终的结果将是一个相当精确地小数,而以IEEE754为标准的double都不能完成这个任务。显然,我们要搬出曾经的噩梦,高精度算法了。
早在大一学习c++时,我就接触过高精度算法的一些基础内容,当时是作为选做的课后题,我用char*
动态分配长度的字符串艰难的完成了+、-、*运算,卡在了除法。这回我先做了一些研究,最后我决定参考这篇博客中提供的代码,利用vector<char>
来比较好的实现一个高精度浮点类。(参考博客中的除法算法不完备,我已改正。另:如有侵权,请告知)
一、类定义
先上代码:
class WFloat //高精度浮点数类
{
//基本运算符重载
friend WFloat operator+(const WFloat&, const WFloat&); //加法重载
friend WFloat operator-(const WFloat&, const WFloat&); //减法重载
friend WFloat operator*(const WFloat&, const WFloat&); //乘法重载
friend WFloat operator/(const WFloat&, const WFloat&) throw(DividedByZeroException); //除法重载
friend WFloat operator-(const WFloat&); //负号重载
//比较重载
friend bool operator==(const WFloat&, const WFloat&); //等于重载
friend bool operator!=(const WFloat&, const WFloat&); //不等于重载
friend bool operator<(const WFloat&, const WFloat&); //小于重载
friend bool operator<=(const WFloat&, const WFloat&); //小于等于重载
friend bool operator>(const WFloat&, const WFloat&); //大于重载
friend bool operator>=(const WFloat&, const WFloat&); //大于等于重载
//扩展运算符重载
friend WFloat operator+=(WFloat&, const WFloat&); //加等重载
friend WFloat operator-=(WFloat&, const WFloat&); //减等重载
friend WFloat operator*=(WFloat&, const WFloat&); //乘等重载
friend WFloat operator/=(WFloat&, const WFloat&); //除等重载
//输入输出重载
friend ostream& operator<<(ostream&, const WFloat&); //输出重载
friend istream& operator>>(istream&, WFloat&); //输入重载
public:
WFloat();
WFloat(int); //用一个整数构造
WFloat(string&); //用一个字符串构造
WFloat(const WFloat&); //用一个高精度数构造
WFloat operator=(const WFloat&); //赋值函数
WFloat abs() const; //取绝对值
~WFloat() {}
static const WFloat ZERO; //定义0
static const WFloat ONE; //定义1
static const WFloat TEN; //定义10(用于除法化整)
private:
vector<char>integer; //整数部分
vector<char>decimal; //小数部分
void trim(); //将多余的零删去
bool tag; //用来表示正负,true为正
};
1、私有成员
首先看私有成员,我们用两个vector<char>
类型的动态数组分别存储浮点数的整数部分和小数部分,我们在读入一个高精度数时(比如用字符串来构造),按照从后(右)往前(左)的顺序分别写入到小数部分和整数部分,以'.'
小数点作为分隔。例如:输入“1234.5678”
,那么小数部分的存储如下8 7 6 5
,整数部分为4 3 2 1
。
正因为我们按照上述的方式存储,因此在小数部分的首部可能会出现多余的0,例如输入"1.5600"
,那么小数部分就是0 0 6 5
,同理可知整数部分的尾部可能会有多余的0。为了解决这个问题,提供了函数trim()来删除多余的0。
对于正负的表示,我们用了一个布尔型的tag标签,这主要是便于条件判断。
2、公有成员
公有成员主要是提供了构造函数,可以看到我们可以使用int、string、WFloat来构造一个高精度浮点数,其中利用string和WFloat构造的情况比较多,int型只是为了表示高精度整型。
我们还定义了三个静态变量,分别是0、1、10,其用处会在运算符重载部分看到。
3、友元函数
友元函数占了最大头,但是没什么好说的,我们的目的就是重载所有的相关运算符,来实现一个可以与double、float近似的高精度浮点类。由于我的需求是完成算数编码,因此我只实现了基础四则运算,布尔运算,如果需要平方、开方等运算,可以自行实现。
二、重要函数实现
因为按照惯例我会在文末给出仓库传送门,所以全部的代码大家都可以查到。出于篇幅的考虑,我决定只将最重要的函数讲解一下(实际上也不少了)
1、构造函数
构造函数我们只讲用string类型构造
WFloat::WFloat(string &num) //用字符串初始化,格式形如"-123.456"、"1.0"
{
bool type = true; //用于判断小数部分是否结束
tag = true; //默认为正数,读到'-'再变为负数
for (string::reverse_iterator iter = num.rbegin(); iter < num.rend(); iter++) //逆向迭代
{
char ch = (*iter);
if (ch == '.') //遇到小数点则开始向整数部分写入
{
type = false;
iter++;
}
if (iter == num.rend() - 1) //读取正负号
{
if (ch == '+')
{
break;
}
if (ch == '-')
{
tag = false;
break;
}
}
//利用逆向迭代器,将整个数据倒序存入
if (type)
decimal.push_back((char)((*iter) - '0'));
else
integer.push_back((char)((*iter) - '0'));
}
}
就像我在类定义里所说的,我们用一个逆向迭代器从后往前的赋值,在遇到小数点之前将字符存入小数部分,之后存入整数部分。
2、trim()
整理函数拿出来说是因为参考博客中写的有一点问题。
void WFloat::trim()
{
//因为我们是逆向存储的,所以整数的尾部和小数的首部可能会有多余的0
vector<char>::reverse_iterator iter = integer.rbegin(); //对整数部分
while (!integer.empty() && (*iter) == 0)
{
integer.pop_back(); //指向不为空且尾部为0,删去
iter = integer.rbegin(); //再次指向尾部
//整数部分的“尾部”就是最高位,如00515.424900的左两个0
}
if (integer.size() == 0 && decimal.size() == 0) //如果整数、小数全为空
{
tag = true;
}
if (integer.size() == 0) //如果整数部分是0
{
integer.push_back(0);
}
vector<char>::const_iterator it = decimal.begin(); //对小数部分
while (!decimal.empty() && (*it) == 0)
{
it = decimal.erase(it); //指向不为空且首部为0,删去
//小数部分的“首部”就是最低位,上例中的右两个0
}
if (decimal.size() == 0) //如果小数部分是0
{
decimal.push_back(0);
}
}
参考博客中对于符号的修改有问题,应该是当整数部分和小数部分同时为0时,才将符号修改为正,而不是任一为0时修改为正。这个问题会影响后面乘法与除法的结果符号,特此说明。
3、输入与输出
3.1 operator<<
ostream& operator<<(ostream& out, const WFloat& num) //输出重载
{
if (!num.tag) //负数
{
out << "-";
}
for (vector<char>::const_reverse_iterator iter = num.integer.rbegin(); iter != num.integer.rend(); iter++) //输出整数部分
{
out << (char)((*iter) + '0');
}
cout << '.';
for (vector<char>::const_reverse_iterator iter = num.decimal.rbegin(); iter != num.decimal.rend(); iter++) //输出小数部分
{
out << (char)((*iter) + '0');
}
return out;
}
输出部分只要注意从后往前的顺序即可。
3.2 operator>>
istream& operator>>(istream& in, WFloat& num) //输入重载
{
string str;
in >> str;
num = WFloat(str);
return in;
}
输入部分我们调用构造函数。
4、布尔判断
我们先写布尔判断部分,因为在计算过程中需要使用到两个高精度数之间的各种判断。
4.1 operator<
小于和等于,通过一些简单的布尔代数运算就可以推导出全部逻辑关系,因此我们只列出小于和等于的定义。
bool operator<(const WFloat& num1, const WFloat& num2) //小于重载
{
bool sign; //返回值
if (num1.tag != num2.tag) //如果异号
{
sign = !num1.tag; //如果num1正,则不小于;反之,则小于
return sign;
}
else
{
//如果同号,先比较整数再比较小数
if (num1.integer.size() != num2.integer.size()) //如果整数部分不等长
{
if (num1.tag) //如果同为正,则整数部分长的大
{
sign = num1.integer.size() < num2.integer.size();
return sign;
}
else
{
//同为负,则整数部分长的小
sign = num1.integer.size() > num2.integer.size();
return sign;
}
}
//如果整数部分等长
vector<char>::const_reverse_iterator iter1, iter2;
iter1 = num1.integer.rbegin();
iter2 = num2.integer.rbegin();
while (iter1 != num1.integer.rend())
{
if (num1.tag && *iter1 < *iter2)
return true;
if (num1.tag && *iter1 > *iter2)
return false;
if (!num1.tag && *iter1 > *iter2)
return true;
if (!num1.tag && *iter1 < *iter2)
return false;
iter1++;
iter2++;
}
//下面比较小数部分
vector<char>::const_reverse_iterator it1, it2;
it1 = num1.decimal.rbegin();
it2 = num2.decimal.rbegin();
while (it1 != num1.decimal.rend() && it2!=num2.decimal.rend())
{
if (num1.tag && *it1 < *it2)
return true;
if (num1.tag && *it1 > *it2)
return false;
if (!num1.tag && *it1 > *it2)
return true;
if (!num1.tag && *it1 < *it2)
return false;
it1++;
it2++;
}
//如果整数部分,而小数部分停止前全部一样,那么看谁的小数位更多
return(num1.tag && it2 != num2.decimal.rend()) || (!num1.tag && it1 != num1.decimal.rend());
}
}
布尔运算这部分主要是情况的考虑完全问题。异号的情况最容易判断,正数为大,因此我们将同号、异号作为最外层的条件判断。
当同号时,先比较整数部分、再比较小数部分。整数部分比较时先比较长度,如果没有结果再逐位比较;整数部分完全相同时,需要逐位比较小数部分。
4.1 operator==
等于和小于的判断逻辑几乎相同,不再复述。
bool operator==(const WFloat& num1, const WFloat& num2) //等于重载
{
if (num1.tag != num2.tag)
return false;
if (num1.integer.size() != num2.integer.size())
return false;
if (num1.decimal.size() != num2.decimal.size())
return false;
//如果长度和符号相同,那么下面逐位比较
vector<char>::const_iterator iter1, iter2;
iter1 = num1.decimal.begin();
iter2 = num2.decimal.begin();
while (iter1 != num1.decimal.end())
{
if (*iter1 != *iter2)
return false;
iter1++;
iter2++;
}
iter1 = num1.integer.begin();
iter2 = num2.integer.begin();
while (iter1 != num1.integer.end())
{
if (*iter1 != *iter2)
return false;
iter1++;
iter2++;
}
return true;
}
5、运算符重载
+、-、*、/
可以转化为+=、-=、*=、/=
,因此我们只需要完成后者。
5.1 operator+=
加、减运算是相对容易完成的部分。我们先上代码,再对其中的部分进行精解。
WFloat operator+=(WFloat& num1, const WFloat& num2) //加等于重载
{
if (num1.tag == num2.tag) //只处理同符号数,异号由-减法处理
{
vector<char>::iterator iter1;
vector<char>::const_iterator iter2, it;
//先处理小数部分
int num1_decimal_size = num1.decimal.size(); //小数部分长度
int num2_decimal_size = num2.decimal.size();
char carry = 0; //进位
if (num1_decimal_size < num2_decimal_size) //如果num2小数部分更长
{
iter1 = num1.decimal.begin();
iter2 = num2.decimal.begin();
iter2 = iter2 - (num1_decimal_size - num2_decimal_size); //将指向调整到一一对应的位置
while (iter1 != num1.decimal.end() && iter2 != num2.decimal.end())
{
(*iter1) = (*iter1) + (*iter2) + carry;
carry = ((*iter1) > 9); //如果大于9则carry=1
(*iter1) = (*iter1) % 10;
iter1++;
iter2++;
}
it = num2.decimal.begin();
iter2 = num2.decimal.end();
iter2 = iter2 - num1_decimal_size - 1; //指向长出部分
while (iter2 != it)
{
num1.decimal.insert(num1.decimal.begin(), *iter2);
iter2--;
}
num1.decimal.insert(num1.decimal.begin(), *iter2);
iter1 = num1.decimal.begin();
}
else
if (num1_decimal_size > num2_decimal_size) //如果num1小数部分更长,同理
{
iter1 = num1.decimal.begin();
iter1 = iter1 + (num1_decimal_size - num2_decimal_size);
//将指向调整到一一对应的位置
iter2 = num2.decimal.begin();
while (iter1 != num1.decimal.end() && iter2 != num2.decimal.end())
{
(*iter1) = (*iter1) + (*iter2) + carry;
carry = ((*iter1) > 9); //如果大于9则carry=1
(*iter1) = (*iter1) % 10;
iter1++;
iter2++;
}
}
else
{
iter1 = num1.decimal.begin(); //如果二者等长
iter2 = num2.decimal.begin();
while (iter1 != num1.decimal.end() && iter2 != num2.decimal.end())
{
(*iter1) = (*iter1) + (*iter2) + carry;
carry = ((*iter1) > 9); //如果大于9则carry=1
(*iter1) = (*iter1) % 10;
iter1++;
iter2++;
}
}
//再处理整数部分
iter1 = num1.integer.begin();
iter2 = num2.integer.begin();
//从个位开始相加
while (iter1 != num1.integer.end() && iter2 != num2.integer.end())
{
(*iter1) = (*iter1) + (*iter2) + carry;
carry = ((*iter1) > 9); //如果大于9则carry=1
(*iter1) = (*iter1) % 10;
iter1++;
iter2++;
}
//总会有一个先到达end()
while (iter1 != num1.integer.end()) //如果被加数更长,处理进位
{
(*iter1) = (*iter1) + carry;
carry = ((*iter1) > 9); //如果大于9则carry=1
(*iter1) = (*iter1) % 10;
iter1++;
}
while (iter2 != num2.integer.end()) //加数更长
{
char val = (*iter2) + carry;
carry = (val > 9);
val %= 10;
num1.integer.push_back(val);
iter2++;
}
if (carry != 0) //如果还有进位,则说明要添加一位
{
num1.integer.push_back(carry);
}
return num1;
}
else
{ //如果异号
if (num1.tag) //如果被加数为正,加数为负,相当于减等于
{
WFloat temp(-num2);
return num1 -= temp;
}
else
{
WFloat temp(-num1);
return num1 = num2 - temp;
}
}
}
可以看到,异号时的加法相当于减法,因此我们的+=
定义中只处理同号情况,异号交由-
处理。
我们的运算操作几乎都是模仿人们的手算进行的,因此就像草纸演算,我们从后往前进行逐位运算。
在计算时首先应当将位数对其,这主要是针对小数部分。运算由三部分组成,当前位被加数、加数、进位(这有点像用代码实现一个加法器),注意对被加数进行模10来保证取值出于0-9之间。
总体来说加减法没有理解难度,并且我的注释很详细,应该不难掌握。
5.2 operator-=
同理加法,我们只处理同号的情况,异号交由+
处理。
WFloat operator-=(WFloat& num1, const WFloat& num2) //减等于重载
{
if (num1.tag == num2.tag) //只处理同号,异号由+加法处理
{
if (num1.tag) //如果同为正
{
if (num1 < num2) //且被减数小
{
WFloat temp(num2 - num1);
num1 = -temp;
return num1;
}
}
else
{
if (-num1 > -num2) //如果同为负,且被减数绝对值大
return num1 = -((-num1) - (-num2));
else
return num1 = (-num2) - (-num1);
}
//下面是同为正,且减数小的情况
//小数部分
char borrow = 0; //借位
int num1_decimal_size = num1.decimal.size();
int num2_decimal_size = num2.decimal.size();
vector<char>::iterator it1 = num1.decimal.begin();
vector<char>::const_iterator it2 = num2.decimal.begin();
if (num1_decimal_size > num2_decimal_size) //如果被减数小数部分更长
{
num1_decimal_size -= num2_decimal_size; //长出部分
it1 = it1 + num1_decimal_size; //跳过长出部分
}
else
{ //如果减数的小数部分更长,则需要给被减数补0
int number = num2_decimal_size - num1_decimal_size;
while (number != 0)
{
num1.decimal.insert(num1.decimal.begin(), 0); //缺少的位数补0
number--;
}
it1 = num1.decimal.begin(); //插入后需要重新指向
it2 = num2.decimal.begin();
}
while ((it1 != num1.decimal.end()) && (it2 != num2.decimal.end()))
{
(*it1) = (*it1) - (*it2) - borrow;
borrow = 0;
if ((*it1) < 0)
{
borrow = 1;
(*it1) += 10;
}
it1++;
it2++;
}
//整数部分
vector<char>::iterator iter1;
vector<char>::const_iterator iter2;
iter1 = num1.integer.begin();
iter2 = num2.integer.begin();
while (iter1 != num1.integer.end() && iter2 != num2.integer.end())
{
(*iter1) = (*iter1) - (*iter2) - borrow;
borrow = 0;
if ((*iter1) < 0) {
borrow = 1;
(*iter1) += 10;
}
iter1++;
iter2++;
}
while (iter1 != num1.integer.end()) {
(*iter1) = (*iter1) - borrow;
borrow = 0;
if ((*iter1) < 0)
{
borrow = 1;
(*iter1) += 10;
}
else break;
iter1++;
}
num1.trim(); //把多余的0去掉
return num1;
}
else
{
//如果异号
if (num1 > WFloat::ZERO)
{
WFloat temp(-num2);
return num1 += temp;
}
else
{
WFloat temp(-num1);
return num1 = -(num2 + temp);
}
}
}
减法需要考虑结果的符号问题,最好的解决办法就是将问题尽可能转化成同一类。在最初的一系列条件判断后,我们只需要处理同为正且减数小于被减数的情况。
注意,在小数部分,给被减数补0的操作结束后,一定要重新将迭代器指向decimal.begin()
。参考博客中没有这两行代码,我在运行时会报错。
剩下的运算部分与加法大同小异,不再复述。
5.3 operator*=
乘除部分的难度就提高了,尤其是除法还要更加复杂一些。我们先看乘法
WFloat operator*=(WFloat& num1, const WFloat& num2) //乘等于重载
{
WFloat result(0); //储存结果
if (num1 == WFloat::ZERO || num2 == WFloat::ZERO) //有0做乘数得0
result = WFloat::ZERO;
else
{
int size = 0;
vector<char>temp_num1(num1.integer.begin(), num1.integer.end()); //一个临时变量,用于将整数部分与小数部分合并
if (num1.decimal.size() != 1 || (num1.decimal.size() == 1 && (*num1.decimal.begin()) != 0)) //如果被乘数有小数部分,插入小数
{
temp_num1.insert(temp_num1.begin(), num1.decimal.begin(), num1.decimal.end());
size += num1.decimal.size();
}
vector<char>temp_num2(num2.integer.begin(), num2.integer.end()); //一个临时变量,用于将整数部分与小数部分合并
if (num2.decimal.size() != 1 || (num2.decimal.size() == 1 && (*num2.decimal.begin()) != 0)) //如果被乘数有小数部分,插入小数
{
temp_num2.insert(temp_num2.begin(), num2.decimal.begin(), num2.decimal.end());
size += num2.decimal.size();
}
//开始乘法
vector<char>::const_iterator iter2 = temp_num2.begin();
while (iter2 != temp_num2.end())
{
if (*iter2 != 0)
{
deque<char>temp(temp_num1.begin(), temp_num1.end());
char carry = 0; //进位
deque<char>::iterator iter1 = temp.begin();
while (iter1 != temp.end()) //被乘数乘以某一位乘数
{
(*iter1) *= (*iter2);
(*iter1) += carry;
carry = (*iter1) / 10;
(*iter1) %= 10;
iter1++;
}
if (carry != 0)
{
temp.push_back(carry);
}
int num_of_zeros = iter2 - temp_num2.begin(); //计算错位
while (num_of_zeros--)
temp.push_front(0); //乘得结果后面添0
WFloat temp2;
temp2.integer.clear();
temp2.integer.insert(temp2.integer.end(), temp.begin(), temp.end());
temp2.trim();
result = result + temp2;
}
iter2++;
}
result.tag = ((num1.tag && num2.tag) || (!num1.tag && !num2.tag));
//由于我们将小数和整数合并在一起,因此下面要把小数点重新添上
if (size != 0)
{
if (size >= result.integer.size()) //说明需要补前导0
{
int n = size-result.integer.size();
for (int i = 0; i <= n; i++)
result.integer.insert(result.integer.end(), 0);
}
result.decimal.clear();
result.decimal.insert(result.decimal.begin(), result.integer.begin(), result.integer.begin() + size);
result.integer.erase(result.integer.begin(), result.integer.begin() + size);
}
}
num1 = result;
num1.trim();
return num1;
}
这里我们开始用到最初定义的静态变量的,如果有乘数为0,那么直接返回0。
否则我们开始运算。小数整数混杂着运算很复杂,因此我们将二者归并到一起,在乘法的运算过程中相当于使用一个大整数进行,最后再补上小数点即可。
运算的过程容易理解,但是在最后拆分小数和整数时,参考博客的代码是有问题的。考虑乘法运算0.545*0.102
,最后的结果是0.0xxx
,这会出现一个问题,那就是我们记录的小数点所在位置size,要大于我们运算结果的长度。这是因为我们需要补充前导0,才能正确的区分整数和小数部分。因此可以看到我再最后添加了一个补充前导0的判断语句。
5.4 operator/=
这部分参考博客的少考虑了一些情况,并且计算结果的小数部分错误的多了一个0,经过我的修正暂时没有发现其他问题。
WFloat operator/=(WFloat& num1, const WFloat& num2) //除等于重载
{
if (num2 == WFloat::ZERO)
throw DividedByZeroException();
if (num1 == WFloat::ZERO)
return num1;
WFloat temp_num1 = num1;
WFloat temp_num2 = num2;
if (temp_num1.tag == false || temp_num2.tag == false) //转换成无符号除法来做
{
temp_num1.tag = true;
temp_num2.tag = true;
}
int Integer_Size = 0; //整数部分应为几位
if ((temp_num2.decimal.size() == 1) && (*(temp_num2.decimal.begin()) == 0)) {} //如果除数没有小数部分,不做操作
else
{
//否则把除数和乘数同时扩大,直到除数为整数(只对Integer部分运算)
int t = temp_num2.decimal.size();
while (t--)
{
temp_num1 = temp_num1 * WFloat::TEN;
temp_num2 = temp_num2 * WFloat::TEN;
}
}
if (temp_num1 < temp_num2) //被除数小于除数,应该是0.xxx
{
while (temp_num1 < temp_num2)
{
temp_num1 *= WFloat::TEN;
Integer_Size--;
}
}
else
{
while (temp_num1 > temp_num2)
{
temp_num1.decimal.push_back(*temp_num1.integer.begin());
temp_num1.integer.erase(temp_num1.integer.begin());
Integer_Size++;
}
}
int k = ACCURACY;
WFloat quotient(0); //商
while (k--)
{
if (temp_num1 < temp_num2)
{
temp_num1 = temp_num1 * WFloat::TEN;
quotient = quotient * WFloat::TEN;
}
else
{
int i;
WFloat compare;
for (i = 1; i <= 10; i++) //“试商”
{
WFloat BF(i);
compare = temp_num2 * BF;
if (compare > temp_num1)
break;
}
compare -= temp_num2;
temp_num1 -= compare;
WFloat index(i - 1);
quotient = quotient + index;
}
}
if (Integer_Size < 0) //如果是小数除以大数,结果为0.xxx
{
vector<char> temp(quotient.integer.begin(), quotient.integer.end());
quotient.integer.clear();
quotient.integer.push_back(0); //整数部分为0
quotient.decimal.clear();
int count_zero = -Integer_Size;
//下面先补充前导0
while (--count_zero)
{
quotient.decimal.insert(quotient.decimal.begin(), 0);
}
quotient.decimal.insert(quotient.decimal.begin(), temp.begin(), temp.end());
}
else
{
if (quotient.integer.size() > Integer_Size)
{
vector<char> temp(quotient.integer.begin(), quotient.integer.end());
quotient.integer.clear(); //这里如果不清空会有错误
quotient.integer.assign(temp.end() - Integer_Size, temp.end());
quotient.decimal.clear(); //同理需要清空
quotient.decimal.insert(quotient.decimal.begin(), temp.begin(), temp.end() - Integer_Size);
}
else
{
//这一部分意义不明,我觉得不会走到这个分支
int t = Integer_Size - quotient.integer.size();
while (t--)
{
quotient = quotient * WFloat::TEN;
}
}
}
quotient.tag = ((num1.tag && num2.tag) || (!num1.tag && !num2.tag));
num1 = quotient;
num1.trim();
return num1;
}
说一下参考博客中的问题:
首先是“试商”的部分,商的结果可以是0-9,参考博客中的写法无法取到0和9,这会导致运算结果的不正确。
另外就是没有考虑到小数除以大数的情况,Integer_Size为负数时说明结果为0.xxx,我们应该补充上前导0才能得到正确的结果。
最后,虽然vector提供的assign函数理论上会清空原始数据,但是我实测,如果不手动clear掉原始数据,那么assign之后会报错。
除法的精度由全局变量ACCURACY决定,这里设置的是100,如果真的要用于算数编码,肯定还是不够的。
总结
以无头苍蝇四处乱撞的方式去写代码总是会走无数的岔路,这次按照参考博客中的思路一步一步来,不断的完善它的错误,也是一种很好的锻炼。所以说,你没必要强迫自己写每一行代码,但你应该读懂自己写下的每一行代码。
本次高精度浮点数内容的具体定义与实现代码可见我的gitee,WFloat.h
头文件,我也提供了测试用的主函数。