这是谁没事肝的题解
2023-10-20 19:32:36
发布于:浙江
13阅读
0回复
0点赞
#pragma once//本题头文件来自git开源仓库,合法使用
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;
class HPFloat
{
private:
long long Digit; //数量级
vector<signed char> 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 <typename Ti>
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 <typename Ty>
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;
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 <signed char>().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;
}
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();
}
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;
}
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;
}
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;
}
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;
}
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);
}
boo
这里空空如也
有帮助,赞一个