高三一模完了,打算趁着寒假好好折腾一下C++。前几天看了一个高精度浮点类WFloat,很有意思
它是通过整数和小数分别处理的方式实现的浮点,但可以注意到,C++中浮点(double、float)是通过数量级进行处理,精度有限但大小是几乎不限。如果仿照它们写一个浮点类,会非常有趣。
数据的存储可以用数组或向量,数组当然会快一些,但考虑到数组实际上有上限,就使用向量,更灵活。至于数量级,锁定记录首位的数量级就好。
先是头文件的引用:
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
再把类体给写出来:
class HPFloat
{
private:
long long Digit; //数量级
vector Num; //数位
bool Symbol; //符号
void empty(); //清空
long long Sdig() const; //有效长度
void Simp(); //去零标准化
void Bspace(); //整体退位
void Mfor(long long x); //前移
void Mback(long long x); //后移
long long Mindig() const; //最小数量级
void Lplus(char op, long long psi); //坐标加法
void Dplus(char op, long long d); //数位加法
void Lsubcor(char op, long long psi); //坐标减法核心
void Lsub(char op, long long psi); //坐标减法
void Dsub(char op, long long d); //数位减法
public:
static bool outtype;
static const HPFloat hpfzero;
HPFloat();
template
HPFloat(Ti value);
HPFloat(const HPFloat &value);
void editlen(long long l); //定义长度
long long Len() const; //全长
string expstr();
double expflo();
HPFloat &operator=(const HPFloat &num);
HPFloat &operator=(const long long &op);
HPFloat &operator=(const string &num);
HPFloat &operator=(const double &num);
HPFloat &operator=(const int &op);
template
HPFloat &operator=(const Ty &op);
friend HPFloat abs(const HPFloat &op1);
friend HPFloat operator+(const HPFloat &op1, const HPFloat &op2);
friend HPFloat operator-(const HPFloat &op1, const HPFloat &op2);
friend HPFloat operator*(const HPFloat &op1, const HPFloat &op2);
friend HPFloat operator/(const HPFloat &op1, const HPFloat &op2);
friend HPFloat operator-(const HPFloat &op);
friend bool operator==(const HPFloat &op1, const HPFloat &op2);
friend bool operator!=(const HPFloat &op1, const HPFloat &op2);
friend bool operator<(const HPFloat &op1, const HPFloat &op2);
friend bool operator<=(const HPFloat &op1, const HPFloat &op2);
friend bool operator>(const HPFloat &op1, const HPFloat &op2);
friend bool operator>=(const HPFloat &op1, const HPFloat &op2);
friend HPFloat operator+=(HPFloat &op1, const HPFloat &op2);
friend HPFloat operator-=(HPFloat &op1, const HPFloat &op2);
friend HPFloat operator*=(HPFloat &, const HPFloat &);
friend HPFloat operator/=(HPFloat &, const HPFloat &);
friend ostream &operator<<(ostream &out, const HPFloat &op);
friend istream &operator>>(istream &in, HPFloat &op);
};
const HPFloat hpfzero(0);
bool HPFloat::outtype=0;
顺便定义一个0,便于后面处理。
然后,功能一一实现。从构造函数出发:
c++在类型转换的时候会调用到构造函数,所以为了兼容其它类型数据,构造函数要能通过参数设定数值。赋值可以交给后面的等号重载实现,所以构造函数的设计不难。可以直接函数模板伺候。
HPFloat::HPFloat()
{
for (int i = 0; i < 16; i++)
{
Num.push_back(0);
}
Symbol = 0;
Digit = 0;
return;
}
template < typename Ti>
HPFloat::HPFloat(Ti value)
{
for (long long i = 0; i < 16; i++)
{
Num.push_back(0);
}
*this=value;
return;
}
考虑到复制构造函数需要带着精度一起传递,单独写出来
HPFloat::HPFloat(const HPFloat& value)
{
vector ().swap(Num);//作为复制构造函数时先清空
for (long long i = 0; i < value.Len(); i++)//按参数的精度构造
{
Num.push_back(value.Num[i]);
}
Digit=value.Digit;
Symbol=value.Symbol;
*this=value;
return;
}
然后要写定义精度的editlen,这玩意也比较容易,不涉及数量级。它要分两种情况考虑,一是扩容,二是收缩。扩容没啥可说的,直接push_back,但收缩时还得考虑下四舍五入,这姑且交给后面的Mback函数,通过反复推拉两次,解决问题。
void HPFloat::editlen(long long l)
{
if (l < 8)//精度过低时直接返回
{
return;
}
if (l > Len())//判断需要扩容还是收缩
{
long long olen = Len();
for (long long i = 0; i < l - olen; i++)
{
Num.push_back(0);
}
}
else
{
Mfor(Len() - Sdig() - 1);
Mback(Len() - l);
Num.erase(Num.end() - Len() + l, Num.end());
}
Simp();
}
然后,解决工具类函数,比较简单。
long long HPFloat::Len() const
{
return Num.size();
}
void HPFloat::empty()
{
for (long long i = 0; i < Len(); i++)//清空数据,保留精度
{
Num[i] = 0;
}
Digit = 0;
return;
}
long long HPFloat::Sdig() const
{
if (Num[Len() - 1] != 0)//如果精度全部占满,返回全长
{
return (Len() - 1);
}
for (long long i = Len() - 1; i >= 0; i--)//计算开头零的数量
{
if (Num[i] == 0)
{
continue;
}
else
{
return i;
}
}
return -1;//全空时返回-1
}
void HPFloat::Simp()
{
long long i = 0;
while (Num[i] == 0)//计算末尾的零
{
i++;
}
if (i == 0)//无需化简,返回
{
return;
}
if (i == Len())//如果全空
{
Digit = 0;
Symbol = 0;//数量级和符号归零
return;
}
else
{
Mback(i);//后退去零
}
}
void HPFloat::Bspace()
{
char a = Num[0];//记录末位
long long sd=Sdig();
for (long long i = 1; i <= sd; i++)
{
Num[i - 1] = Num[i];
Num[i] = 0;
}
if (a >= 5)//四舍五入
{
Lplus(1, 0);
}
return;
}
void HPFloat::Mfor(long long x)
{
if (x == 0)
{
return;
}
if (x < 0)//负值则后移
{
Mback(-x);
return;
}
long long sd=Sdig();
for (long long i = sd; i >= 0; i--)
{
Num[x + i] = Num[i];
Num[i] = 0;
}
return;
}
void HPFloat::Mback(long long x)
{
if (x == 0)
{
return;
}
if (x < 0)
{
Mfor(-x);
return;
}
char t = 0;
long long l = Sdig();
if (x > l + 1)//移动大于精度,全清,保留数量级
{
for (long long i = 0; i <= l; i++)
{
Num[i] = 0;
}
return;
}
if (x == l + 1)
{
t = Num[l];
}
for (long long i = x; i <= l; i++)
{
Num[i - x] = Num[i];
Num[i] = 0;
}
for (long long i = l - x + 1; i < Len(); i++)//清理未移动的数位
{
Num[i] = 0;
}
if (t >= 5)
{
Lplus(1, 0);//四舍五入后进位
}
return;
}
long long HPFloat::Mindig() const
{
return Digit - Sdig();
}
然后,噩梦开始,整个……先不急着搞运算,从比较开始。
大于、小于比较,按符号→数量级→首位开始各数位的顺序比就好
>=、<=、==就更没啥了
bool operator==(const HPFloat &op1, const HPFloat &op2)
{//先判断符号、数量级、已用精度
if (!(op1.Digit == op2.Digit && op1.Sdig() == op2.Sdig() && op1.Symbol == op2.Symbol))
{
return 0;
}
long long ago=op1.Sdig();//很久以前,C++是多么艺术❛‿˂̵✧
for (long long i = 0; i <= ago; i++)
{
if (op1.Num[i] != op2.Num[i])//数位一一比较
{
return 0;
}
}
return 1;//全部通过,输出1
}
bool operator!=(const HPFloat &op1, const HPFloat &op2)
{
return !(op1 == op2);
}
bool operator<(const HPFloat &op1, const HPFloat &op2)
{//按符号、数量级、已用精度、各数位的顺序比较
if (op1 == hpfzero && op2 != hpfzero)//判断零
{
return !op2.Symbol;
}
if (op2 == hpfzero)//零的数量级比较特殊,不参与比较
{
return op1.Symbol;
}
if (op1.Symbol != op2.Symbol)//比较符号
{
return op1.Symbol;
}
if (op1.Digit != op2.Digit)//比较数量级
{
return (op1.Digit < op2.Digit);
}
long long sd1=op1.Sdig();
long long sd2=op2.Sdig();
long long t = (sd1 < sd2) ? sd1 : sd2;//提前准备数据,提升效率
for (long long i = 0; i <= t; i++)
{
if (op1.Num[sd1 - i] != op2.Num[sd2 - i])
{
return (op1.Num[sd1 - i] < op2.Num[sd2 - i]);//比较各数位
}
}
if (sd1 < sd2)//比较已用精度
{
return 1;
}
return 0;
}
bool operator<=(const HPFloat &op1, const HPFloat &op2)
{
return (op1 < op2 || op1 == op2);
}
bool operator>(const HPFloat &op1, const HPFloat &op2)
{//和<基本一致
if (op1 == hpfzero)
{
return op2.Symbol;
}
if (op2 == hpfzero && op1 != hpfzero)
{
return !op1.Symbol;
}
if (op1.Symbol != op2.Symbol)
{
return op2.Symbol;
}
if (op1.Digit != op2.Digit)
{
return (op1.Digit > op2.Digit);
}
long long sd1=op1.Sdig();
long long sd2=op2.Sdig();
long long t = (sd1 < sd2) ? sd1 : sd2;
for (long long i = 0; i <= t; i++)
{
if (op1.Num[sd1- i] != op2.Num[sd2 - i])
{
return (op1.Num[sd1 - i] > op2.Num[sd2 - i]);
}
}
if (sd1 > sd2)
{
return 1;
}
return 0;
}
bool operator>=(const HPFloat &op1, const HPFloat &op2)
{
return (op1 > op2 || op1 == op2);
}
然后是负号和绝对值
HPFloat abs(const HPFloat &op)
{
HPFloat ans(op);
ans.Symbol = 0;
return ans;
}
HPFloat operator-(const HPFloat &op)
{
HPFloat ans(op);
ans.Symbol = !op.Symbol;
return ans;
}
再往后,运算开始
加法优先,我的思路是劈开处理,从整个数,劈开成个位数,然后把数量级换算成坐标。于是,先写坐标运算。输入一个要加的数值和位置,递归进位。顶到头就退一位精度,首位进位时把数量级也进一位。
void HPFloat::Lplus(char op, long long psi)
{
if (psi > Sdig())//如果在已用精度之前,直接填充
{
Digit += (psi - Sdig());
Num[psi] = op;
Simp();
return;
}
Num[psi] += op;
if (Num[psi] >= 10)//是否进位
{
if (psi == (Len() - 1))//如果精度已满
{
Bspace();//退格让出一位精度
Digit++;
Num[psi] = 1;
}
else
{
Lplus(1, psi + 1);
}
}
for (long long i = 0; i < Len(); i++)//处理进位剩下的数据。
{//不在进位时处理为防止出现重复运算
if (Num[i] >= 10)
{
Num[i] -= 10;
}
}
Simp();
return;
}
然后是数位加法,把数量级换算到坐标。先判断精度够不够,如果精度够不着,就直接return,能够着就整体平移使末位与之对齐。
void HPFloat::Dplus(char op, long long d)
{
Simp();
if (Digit >= d) //判断谁的数量级大
{
if (Digit - (Len() - 1) - 1 > d)//够不着就直接return
{
return;
}
if (Digit - (Len() - 1) - 1 == d)//差一位就四舍五入掉
{
if (op >= 5)
{
Mfor(Len() - Sdig() - 1);
Lplus(1, 0);
return;
}
else
{
return;
}
}
if (Mindig() <= d)//是否需要平移来对齐
{
Lplus(op, Sdig() - (Digit - d));
}
else
{
Mfor(Mindig() - d);
Num[0] = op;
}
}
else
{
if (Mindig() + Len() - 1 >= d)//是否需要平移
{
Num[d - Digit + Sdig()] = op;//精度足够,直接填充
Digit = d;
}
else
{
Mback(d - (Mindig() + Len() - 1));//精度不足,把自己舍掉
Num[Len() - 1] = op;
Digit = d;
}
}
Simp();
return;
}
然后加等,直接把数位一个个拆开传入即可。加法就调用加等。
HPFloat operator+=(HPFloat &op1, const HPFloat &op2)
{
if (op1.Symbol != op2.Symbol)//如果符号不同,传递给减法
{
HPFloat op3(op2);
if (op1.Symbol == 1)
{
op1.Symbol = 0;
op3 -= op1;
op1 = op3;
return op1;
}
else
{
op3.Symbol = 0;
op1 -= op3;
return op1;
}
}
{
if (op1 == hpfzero)//如果为零,直接返回
{
op1 = op2;
return op1;
}
}
long long sd=op2.Sdig();
long long mi=op2.Mindig();
for (long long i = 0; i <= sd; i++)//一个个传入到Dplus
{
op1.Dplus(op2.Num[i], mi + i);
}
HPFloat ans(op1);
return ans;
}
HPFloat operator+(const HPFloat &op1, const HPFloat &op2)
{
HPFloat op3(op1);
op3 += op2;
return op3;
}
减法,实在是难伺候。如果在首位以外减时每一位都要循环退位,过于复杂,所以先姑且禁止小减大。因为减法的数量级可能”突变“,例如1001-1000,数量级从3直接跳到1。因为减法不会增加数量级不用考虑进位,所以我把减法的递归运算部分和数量级运算部分分开,单个数位计算完后统一处理数量级。其他部分和加法类似,从坐标运算开始。
void HPFloat::Lsubcor(char op, long long psi)
{
Num[psi] -= op;
if (Num[psi] < 0)
{
Lsubcor(1, psi + 1);//递归借位
}
for (long long i = 0; i < Len(); i++)//处理借位剩下的负值
{
if (Num[i] < 0)
{
Num[i] += 10;
}
}
}
void HPFloat::Lsub(char op, long long psi)//递归处理后再计算数量级
{
long long ld = Sdig();
Lsubcor(op, psi);
Digit -= ld - Sdig();
Simp();
return;
}
数位运算上和加法基本一致。
void HPFloat::Dsub(char op, long long d)
{
if (Digit - (Len() - 1) - 1 > d) //够不着就直接return
{
return;
}
if (Digit - (Len() - 1) - 1 == d)//差一位就四舍五入掉
{
if (op >= 5)
{
Mfor(Len() - Sdig() - 1);
Lsub(1, 0);
return;
}
else
{
return;
}
}
if (Mindig() <= d)//是否需要平移来对齐
{
Lsub(op, Sdig() - (Digit - d));
}
else
{
Mfor(Mindig() - d);
Lsub(op, 0);
}
Simp();
return;
}
减法就通过循环传递参数到Dsub
HPFloat operator-=(HPFloat &op1, const HPFloat &op2)
{
HPFloat ans(op1);
ans = op1 - op2;
op1 = ans;
return ans;
}
HPFloat operator-(const HPFloat &op1, const HPFloat &op2)
{
if (op1.Symbol != op2.Symbol)//符号不同就传递给加法
{
if (op1.Symbol == 1)
{
HPFloat ans(op1);
ans.Symbol = 0;
ans = op1 + op2;
ans.Symbol = 1;
return ans;
}
else
{
HPFloat ans(op2);
ans.Symbol = 0;
ans += op1;
return ans;
}
}
if (op1 == hpfzero)
{
return -op2;
}
bool bg=(op1 >= op2);//确保传递时不发生小减大
HPFloat ans(bg ? op1 : op2);
HPFloat op((!bg)?op1 : op2);
ans.Symbol = (!bg);
ans.Simp();
long long D = op.Mindig();
long long sd=op.Sdig();
for (long long i = 0; i <= sd; i++)//循环传递参数
{
ans.Dsub(op.Num[i], D + i);
}
return ans;
}
加减两个基础运算伺候完了,剩下乘除只要基于它们进行就好。
乘法,就让每两位相乘然后带着数量级相加即可
HPFloat operator*(const HPFloat &op1, const HPFloat &op2)
{
HPFloat ans;
ans.editlen(op1.Len());
long long sd1=op1.Sdig();
long long sd2=op2.Sdig();
long long mi1=op1.Mindig();
long long mi2=op2.Mindig();//提前提取需要重复使用的数据,提升效率
for (long long i = 0; i <= sd1; i++)
{
for (long long j = 0; j <= sd2; j++)
{
char t = op1.Num[i] * op2.Num[j];
if (t==0)
{
continue;//零不参与运算
}
HPFloat temp;
temp = t;
temp.Digit = mi1 + mi2 + i + j + (t >= 10);//计算两位相乘的数量级
ans += temp;//直接加进去
}
}
ans.Symbol = (op1.Symbol != op2.Symbol);//同号为正,异号为负
return ans;
}
HPFloat operator*=(HPFloat &op1, const HPFloat &op2)
{
op1 = op1 * op2;
HPFloat ans(op1);
return ans;
}
除法,模仿竖式运算,通过减来实现,减到精度用尽为止。多一位精度为了四舍五入。
HPFloat operator/(const HPFloat &op1, const HPFloat &op2)
{
if (op2 == hpfzero)//定义除零错误
{
throw("ZeroDivide");
}
HPFloat ans;
ans.editlen(op1.Len()+1);
HPFloat num1(op1);
HPFloat num2(op2);
ans.Symbol = !(op1.Symbol == op2.Symbol);//确定符号
ans.Digit = op1.Digit - op2.Digit;//确定数量级
num1.Digit = 0;
num2.Digit = 0;
num1.Symbol = 0;
num2.Symbol = 0;//全部对齐,便于运算
ans.Digit -= (num1 < num2);//确定数量级
for (long long i = ans.Len() - 1; i >= 0; i--)//遍历ans输入商
{
while (num1 >= num2)//得出商
{
ans.Num[i]++;
num1 -= num2;
}
if (num1 == hpfzero || num2 == hpfzero)//除尽时退出
{
break;
}
num2.Digit--;
}
ans.Mback(1);//退位,四舍五入掉最后一位
ans.Simp();
HPFloat temp(ans);
return temp;
}
HPFloat operator/=(HPFloat &op1, const HPFloat &op2)
{
op1 = op1 / op2;
HPFloat ans(op1);
return ans;
}
之前一直用着的等号重载,先是自己跟自己赋值,要考虑四舍五入:
HPFloat &HPFloat::operator=(const HPFloat &op)
{
HPFloat num;//定义一个临时对象,避免遇到如a=a的语句时出现问题
num.editlen(op.Len());
long long sd=op.Sdig();
for (long long i = 0; i <=sd; i++)
{
num.Num[i] = op.Num[i];
}
num.Digit = op.Digit;
num.Symbol = op.Symbol;//需要手动负值,因为构造函数会调用=
empty();
long long i = (Len() - 1 > sd) ? sd : (Len() - 1);
for (long long j = 0; j <= i; j++)
{
Num[Len() - 1 - j] = num.Num[sd - j];
}
if (!((Len() - 1) >= sd))
{
if (num.Num[sd - (Len() - 1) - 1] >= 5)//精度不足时四舍五入
{
Lplus(1, 0);
}
}
Symbol = num.Symbol;
Digit = num.Digit;
Simp();
return *this;
}
然后,当然要支持和整型的赋值。鉴于long long最长且其他整型都可以转换成它,就用它解决整型。把每一位循环读出存入就好:
HPFloat &HPFloat::operator=(const long long &op)
{
empty();
long long num = (op > 0) ? op : -op;//取正
short e = 0;
{
long long t = 1;
while (t <= num)
{
e++;//计算数位
t *= 10;
}
}
for (short i = 0; i <= e; i++)
{
Num[i] = num % 10;//逐个填入
num = (num - num % 10) / 10;
}
Digit = e - 1;
Symbol = (op < 0);
Simp();
return *this;
}
int类型比较常用,转换成long long存入:
HPFloat &HPFloat::operator=(const int &op)//int较常用,不参与函数模板提升效率
{//longlong可兼容int,调用longlong
return *this = (long long)op;
}
然后,要支持和最万能的string转换。这一步最复杂,需要先切掉符号,结束符;要支持科学计数法;还要考虑到用户可能输入一些不太规范的内容,如开头多出很多0、小数点加在了开头或结尾……什么?你还要输一些汉字和字母?我直接给你throw算了。
那就先扫描有没有e或E,有就先录入数量级,然后把e之后的切掉,继续提取各数位。遇到小数点就再修改一遍数量级,继续录入;发现在48到57之外的字符,就throw
HPFloat &HPFloat::operator=(const string &num)
{
HPFloat temp;
temp.editlen(num.size());
unsigned long eloc = 0;
while (num[eloc] != 'e' && num[eloc] != 'E' && eloc <= (num.size() - 1))//如果是科学计数法,先提出数量级
{
eloc++;
}
if (eloc < num.size() - 1)
{
temp.Digit = stoll(num.substr(eloc + 1, num.size() - 1));//写入数量级
}
string op = num.substr(0, eloc );
{
if (op[0] == '-')//提出负号
{
temp.Symbol = 1;
op.erase(0, 1);
}
{
long long l = 0;
while (op[l] == '0')//删掉多余的零
{
l++;
}
if (l != 0)
{
op.erase(0, l);
}
}
reverse(op.begin(), op.end());//倒序,和HPFloat的顺序相同
if (op[0] == '\0')//删掉结束符
{
op.erase(0, 1);
}
bool ifdot = 0;
long long dotloc = 0;
for (unsigned long long i = 0; i < op.size(); i++)
{
if (op[i] == '.')//记录小数点的位置
{
ifdot = 1;
dotloc = i;
continue;
}
if (op[i] < 48 || op[i] > 57)//遇到异常数据,抛出错误
{
throw("DataException");
return *this;
}
temp.Num[i - ifdot] = op[i] - 48;//录入数据
}
if (op[op.size() - 1] == '.')//如果小数点在末尾
{
op.erase(op.size() - 1, 1);
long long l = 0;
while (op[op.size() - 1 - l] == '0')
{
l++;
}
temp.Digit += -l - 1;//算出数量级
}
else
{
temp.Digit += op.size() - 1 - dotloc - ifdot;//算出数量级
}
temp.Simp();//化简返回
*this = temp;
return *this;
}
}
浮点数就可以先转成字符再录入
HPFloat &HPFloat::operator=(const double& num)
{
char tem[16]= {0};
sprintf(tem,"%f",num);//打印到字符串
string str=tem;
*this=str;//调用等号重载
return *this;
}
其它类型,转成浮点伺候
template < typename Ty>
HPFloat &HPFloat::operator=(const Ty &op)
{
return *this = (double)op;//转换到浮点
}
然后,搞一下输出,写两个类型转换函数。转到浮点比较简单,循环加就行;转到字符稍复杂,不过比录入简单一些
string HPFloat::expstr()
{
string str;
if (!outtype)//判断输出类型
{
if (Symbol==1)//正负
{
str+='-';
}
if (Digit < 0)//是否需要补零
{
str+= "0.";
for (long long i = -1; i > Digit; i--)
{
str+= '0';
}
}
for (long long i = Sdig(); i >= 0; i--)
{
str+= (char)((int)Num[i]+48);//循环输出
if (Sdig() - i == Digit && i != 0)
{
str+= '.';//小数点
}
}
for (long long i = Mindig(); i > 0; i--)//结尾补零
{
str+= '0';
}
}
else
{
if (Symbol==1)
{
str+='-';
}
str+= (char)((int)Num[Sdig()]+48);
str+= '.';//把首位和.先输出
for (long long i = Sdig() - 1; i >= 0; i--)
{
str+= (char)((int)Num[i]+48);//循环输出
}
str+= 'e' << Digit;//输出数量级
}
return str;
}
double HPFloat::expflo()
{
double ans=0;
double temp=0;
for (long long i = 0; i <= Sdig(); i++)
{
temp=Num[i];
temp*=pow(10,Mindig()+i);
ans+=temp;//循环加法输出
}
return ans;
}
输入输出,输出直接照抄expstr即可,输入嘛,就拿string做个介质
考虑到string理论上有上限,所以输出不调用expstr
istream &operator>>(istream &in, HPFloat &op)
{
string temp;
in >> temp;//输入到字符,调用等号重载
op = temp;
return in;
}
ostream &operator<<(ostream &out, const HPFloat &op)
{//和expstr基本相同。因为string理论上有上限,所以这里不调用expstr
if (!op.outtype)
{
if (op.Symbol==1)
{
out<<'-';
}
if (op.Digit < 0)
{
out << "0.";
for (long long i = -1; i > op.Digit; i--)
{
out << '0';
}
}
for (long long i = op.Sdig(); i >= 0; i--)
{
out << (int)op.Num[i];
if (op.Sdig() - i == op.Digit && i != 0)
{
out << '.';
}
}
for (long long i = op.Mindig(); i > 0; i--)
{
out << '0';
}
}
else
{
if (op.Symbol==1)
{
out<<'-';
}
out << (int)op.Num[op.Sdig()] << '.';
for (long long i = op.Sdig() - 1; i >= 0; i--)
{
out << (int)op.Num[i];
}
out << 'e' << op.Digit;
}
return out;
}
到此,整个类大概就完事了,测试、、、测试,简直不敢运行,一出毛病就得查几个小时
//测试函数
#include
#include
#include "HPFloat.h"
using namespace std;
int main()
{
HPFloat a;
a.editlen(600);
HPFloat b(a);
cin >> a >> b;
cout << "---------------------------" << endl;
cout << "a:" << a << "\nb:" << b << endl;
cout << endl;
cout << "a>b?:"<<(a > b);
cout << endl;
cout << "a+b:"<<(a + b);
cout << endl;
cout << "a-b:"<< (a - b);
cout << endl;
HPFloat::outtype = 1;
cout << "a*b:"<< (a * b);
cout << endl;
cout << "a/b:"<< (a / b);
getch();
return 0;
}
除法计算稍慢一点,毕竟300位……这谁知道算的对不对呢,换了几个小点的数,计算器摁一摁,大概是没问题
完整的HPFloat.h可以见我的Gitee:
HPFloat.h · GlowingBrick/Do As One Pleases - Gitee.com