📄 arithmetic.cpp
字号:
#include "Arithmetic.h"
#include <vector>
long Arithmetic::m_precision = 15;//精度
int Arithmetic::m_Tstate = 0;//计算三角函数时 0表示数值为角度, 2表示数值为弧度
std::string Arithmetic::pai = "3.1415926535897932";//π
/*******************************************************\
函数: Arithmetic构造函数
功能: 初始化空字符串
输入: 无
输出: 无
返回: 无
备注: 无
\*******************************************************/
Arithmetic::~Arithmetic()
{
m_num = "";
m_Tstate = 0;
}
/*******************************************************\
函数: Arithmetic构造函数
功能: 赋值
输入: 字符串
输出: 无
返回: 无
备注: 无
\*******************************************************/
Arithmetic::Arithmetic()
{
m_num = "";
}
Arithmetic::Arithmetic(std::string num)
{
m_num = num;
}
Arithmetic::Arithmetic(char c)
{
char a[2];
a[0] = c;
a[1] = '\0';
m_num = a;
}
/*******************************************************\
函数: Arithmetic构造函数
功能: 赋值
输入: 字符串
输出: 无
返回: 无
备注: 无
\*******************************************************/
Arithmetic::Arithmetic(const Arithmetic& data)// const
{
m_num = data.GetData();
}
/*******************************************************\
函数: Atol
功能: 字符转数字
输入: 字符
输出: 无
返回: 字符对应的数字
备注: 无
\*******************************************************/
int Arithmetic::Atol(char c)
{
return c - '0';
}
/*******************************************************\
函数: Compare
功能: 比较数字大小
输入: 字符串
输出: 无
返回: 0 一样大, 1 左边大, 2 右边大
备注: 无
\*******************************************************/
int Arithmetic::Compare(std::string& left, std::string& right)
{
int i;
for (i = 0;i < left.length() && left[i] == right[i];++i);
if(i == left.length())
return 0;
return left[i] > right[i] ? 1 : 2;
}
/*******************************************************\
函数: SumCarry
功能: 加减法时进位退位
输入: 2个位数之和,进位退位数.
输出: 无
返回: 无
备注: 无
\*******************************************************/
void Arithmetic::SumCarry(int& sum, int& carry)
{
if(sum < 0)
{
sum += 10;
carry = -1;
return;
}
if(sum >= 10)
{
sum -= 10;
carry = 1;
return;
}
if(sum < 10 && sum >= 0)
carry = 0;
}
/*******************************************************\
函数: Operation
功能: 加减运算
输入: 2个大数, plus判断加减运算, state判断状态
输出: 无
返回: 无
备注: 无
\*******************************************************/
void Arithmetic::Operation(const std::string& left, const std::string& right, std::string& outcome, int& carry, int greater, int state, int plus)
{
int i;
char c;
for (i = left.length()-1;i >= 0;--i)
{
int sum;
if(state == 0 || greater == 0 && state == -1)
sum = 0;
if(greater == 1 && state == -1)
sum = Atol(left[i]) - Atol(right[i]) + carry;
if(greater == 2 && state == -1)
sum = Atol(right[i]) - Atol(left[i]) + carry;
if(state == 1 || greater == 0 && state == 1)
sum = Atol(left[i]) + Atol(right[i]) + carry;
if(i == 0 && plus == 1){}
else
SumCarry(sum, carry);
c = Itoa(sum);
switch(c)
{
case 'A':
outcome += "01";
break;
case 'B':
outcome += "11";
break;
case 'C':
outcome += "21";
break;
case 'D':
outcome += "31";
break;
case 'E':
outcome += "41";
break;
case 'F':
outcome += "51";
break;
default:
outcome += c;
}
}
}
/*******************************************************\
函数: Itoa
功能: 数字转字符
输入: 个位数
输出: 无
返回: 个位数字对应的字符
备注: 无
\*******************************************************/
char Arithmetic::Itoa(int n)
{
char *a = "0123456789ABCDEF";
return a[n - 0];
}
/*******************************************************\
函数: Multiply
功能: 计算大数乘法
输入: 无
输出: 无
返回: 积
备注: 重载的 * 中调用此函数
\*******************************************************/
std::string Arithmetic::Multiply(std::string left, std::string right, int digCount)
{
using namespace std;
Arithmetic sum = "0";
int il;
for (il = left.length() - 1;il >= 0;--il)
{
int ir, carry = 0;
vector<string> strVector;
std::string t = "";
for (ir = right.length() - 1;ir >= 0;--ir)
{
char a[2], b[2];
a[0] = left[il];
b[0] = right[ir];
a[1] = '\0';
b[1] = '\0';
std::string h;
strVector.insert(strVector.end(), h = MulChar(a, b, carry));
}
if(carry != 0)
{
char c[3];
itoa(carry, c, 10);
strVector.insert(strVector.end(), c);
}
for(int i = strVector.size() - 1;i >= 0;--i)
t += strVector[i];
for (ir = left.length() - 1;ir != il;--ir)
t += "0";
Arithmetic str = t;
sum = sum + str;
}
if(digCount >= sum.GetData().length())
{
int i = digCount - sum.GetData().length();
std::string t = sum.GetData();
while(i--)
t.insert(0, "0");
for (i = t.length()-1;t[i] == '0';--i)
t.erase(i, 1);
if(t != "")
t.insert(0, "0.");
else
t = "0";
sum = t;
}
else
{
std::string t = sum.GetData();
t.insert(sum.GetData().length() - digCount, ".");
for (int i = t.length()-1;t[i] == '0';--i)
t.erase(i, 1);
if(t[t.length()-1] == '.')
t.erase(t.length()-1, 1);
sum = t;
}
return sum.GetData();
}
/*******************************************************\
函数: MulChar
功能: 计算大数乘法
输入: 无
输出: 无
返回: 积
备注: 重载的 * 中 Multiply 中 调用此函数
\*******************************************************/
std::string Arithmetic::MulChar(char *a, char *b, int& carry)
{
int t = atoi(a) * atoi(b) + carry;
if(t >= 10)
{
carry = t / 10;
t %= 10;
}
else
carry = 0;
char c[5];
itoa(t, c, 10);
std::string str = c;
return str;
}
/*******************************************************\
函数: Dividle
功能: 计算大数除法
输入: 无
输出: 无
返回: 商
备注: 重载的 / 中调用此函数
\*******************************************************/
std::string Arithmetic::Dividle(std::string numa, std::string numb, long m_precision)
{
while(numb[0] == '0')
numb.erase(0, 1);
while(numa[0] == '0')
numa.erase(0, 1);
std::string result = "";
int dig = 0;
long ia = numa.length(), ib = numb.length(), nPrec = 0, lcarry = 0;
if(ia < ib)//计算前确保字符串numa > numb
{
result = "0.";
dig = 1;
for (long i = 0;i < ib - ia;++i)
{
result += "0";
numa += "0";
}
lcarry = numa.length();
Arithmetic inuma = numa, inumb = numb, iresult = "";
iresult = inuma - inumb;
if(iresult.GetData()[0] == '-')
{
// result += "0";
numa += "0";
// ++nPrec;
}
else
{
result.erase(result.length()-1, 1);
}
}
else//计算前确保字符串numa > numb
{
if(ia == ib)
{
Arithmetic inuma = numa, inumb = numb, iresult = "";
iresult = inuma - inumb;
if(iresult.GetData()[0] == '-')
{
result = "0.";
numa += "0";
dig = 1;
lcarry = numa.length();
}
}
else
lcarry = numa.length();
}
do
{
if(numa[0] == '0')//处理1000...类似的数据
{
while(numa[0] == '0')
{
numa.erase(0, 1);
result += "0";
}
}
if(numa.length() < ib)//每次运算前都会确保大于numb
{
ia = numa.length();
if(dig == 0)
{
dig = 1;
long i;
for (i = 1;i < ia - lcarry;++i)
result += "0";
result += ".";
for (i = ib - ia;i != 0;--i)
numa += "0";
for (i = ib - lcarry - 1;i != 0;--i)
result += "0";
Arithmetic inuma = numa, inumb = numb, iresult = "";
iresult = inuma - inumb;
lcarry = numa.length();
if(iresult.GetData()[0] == '-')
{
numa += "0";
result += "0";
}
}
else
{
if(numa.length() == ib)
{
Arithmetic inuma = numa, inumb = numb, iresult = "";
iresult = inuma - inumb;
if(iresult.GetData()[0] == '-')
{
numa += "0";
result += "0";
}
}
else
{
long i = 0;
for (i = ib - ia;i != 0;--i)
numa += "0";
for (i = ib - lcarry - 1;i != 0;--i)
result += "0";
Arithmetic inuma = numa, inumb = numb, iresult = "";
iresult = inuma - inumb;
lcarry = numa.length();
if(iresult.GetData()[0] == '-')
{
numa += "0";
result += "0";
}
}
}
}
else
{
if(numa.length() == ib)
{
long ia = numa.length();
Arithmetic inuma = numa, inumb = numb, iresult = "";
iresult = inuma - inumb;
if(iresult.GetData()[0] == '-')
{
if(dig == 0)
{
result += ".";
dig = 1;
}
numa += "0";
// result += "0";
}
}
}
std::string t = numa.substr(0, ib), carry = "";
numa.erase(0, ib);
Arithmetic inuma = t, inumb = numb, iresult = "";
iresult = inuma - inumb;
if(iresult.GetData()[0] == '-')
{
if(numa != "")////做10000 / 10 时,加上numa空字符串 numa[0]时会有意想不到的BUG,所以用了if
{
long i1 = t.length() - lcarry;
for (long i = 0;i < i1;++i)
result += "0";
t += numa[0];
numa.erase(0, 1);
}
}
long count = 0;
do
{
inuma = t;
iresult = inuma - inumb;
if(iresult.GetData()[0] != '-')
{
t = iresult.GetData();
++count;
}
}while(iresult.GetData()[0] != '-');
while(t[0] == '0')
t.erase(0, 1);
if(t == "")
t = "0";
carry = t;
char *pc = new char[15];
itoa(count, pc, 10);
// if(result == "1400657190290894403272006596")
// std::cout << result << std::endl;
if(strcmp(pc, "0"))
result += pc;
delete [] pc;
if(carry != "0" && carry != "")
numa.insert(0, carry);
lcarry = carry.length();
if(carry == "" || carry == "0")
lcarry = 0;
if(result.find(".") < result.length())
nPrec = result.length()-1 - result.find(".");
}while(numa != "" && nPrec <= m_precision+1);
if(result.find(".") < result.length())
{
while(result[result.length()-1] == '0')
result.erase(result.length()-1, 1);
}
else
{
if(result != "0")
{
while(result[0] == '0')
result.erase(0, 1);
}
}
if(result[result.length()-1] == '.')
result.erase(result.length()-1, 1);
if(result.find(".") < result.length())
{
if(result.length() - result.find(".") > m_precision+1)
{
for (long i = result.find(".")+1;result[i] == '0';++i);
if(i < result.find(".")+1 + m_precision+1)
result.erase(result.find(".") + m_precision+2, result.length());
}
}
return result;
}
/*******************************************************\
函数: PlusMinus
功能: 计算大数加减法
输入: 无
输出: 无
返回: 和或差
备注: 加减法通用,减法时需将被减数加1负号再调用此函数
\*******************************************************/
std::string Arithmetic::PlusMinus(std::string &left, std::string &right)
{
std::string tInteger = "0", tDigits = "0";
std::string ledigits = "0", ridigits = "0";
std::string result = "";
int state, lsign = 1, rsign = 1, greater, i, carry = 0, plus;
if(left[0] == '-')
{
left.erase(0, 1);
lsign = -1;
}
if(right[0] == '-')
{
right.erase(0, 1);
rsign = -1;
}
if((i = left.find('.')) < left.length())
{
ledigits = left.substr(i+1, left.length() - i - 1);
left.erase(i, left.length() - i);
}
if((i = right.find('.')) < right.length())
{
ridigits = right.substr(i+1, right.length() - i - 1);
right.erase(i, right.length() - i);
}
StringInsert(left, right, 1);//填充0,使长度相等
StringInsert(ledigits, ridigits, 2);//填充0,使长度相等
greater = Compare(left, right);
if(greater == 0)
greater = Compare(ledigits, ridigits);
state = lsign == rsign ? lsign : greater == 0 ? 0 : greater == 1 ? lsign : rsign;
plus = lsign == rsign ? 1 : -1;
Operation(ledigits, ridigits, tDigits, carry, greater, plus, 0);
Operation(left, right, tInteger, carry, greater, plus, 1);
tInteger.erase(0, 1);
tDigits.erase(0, 1);
std::reverse(tInteger.begin(), tInteger.end());
for (i = 0;i < tInteger.length() && tInteger[i] == '0';++i);
tInteger.erase(0, i);
for (i = 0;i < tDigits.length() && tDigits[i] == '0';++i);
tDigits.erase(0, i);
std::reverse(tDigits.begin(), tDigits.end());
if(tInteger == "\0" && tDigits != "\0")
{
if(state == -1)
result += "-";
result = result + "0" + "." + tDigits;
}
if(tInteger != "\0" && tDigits != "\0")
{
if(state == -1)
result += "-";
result = result + tInteger + "." + tDigits;
}
if(tInteger != "\0" && tDigits == "\0")
{
if(state == -1)
result += "-";
result = result + tInteger;
}
if(tInteger == "\0" && tDigits == "\0")
result += "0";
return result;
}
/*******************************************************\
函数: StringInsert
功能: 填充0,使长度相等
输入: 无
输出: 无
返回: 无
备注:ntype = 1代表填充整数部分,2代表填充小数部分
\*******************************************************/
void Arithmetic::StringInsert(std::string& left, std::string& right, int ntype)
{
std::string t;
int i;
for (i = abs((int)left.length() - (int)right.length());i > 0;--i)
t += "0";
if(left.length() > right.length() && ntype == 1)
right.insert(0, t);
if(left.length() < right.length() && ntype == 1)
left.insert(0, t);
if(left.length() > right.length() && ntype == 2)
right.insert(right.length(), t);
if(left.length() < right.length() && ntype == 2)
left.insert(left.length(), t);
}
/*******************************************************\
函数: GetData()
功能: 获取类成员
输入: 无
输出: 无
返回: m_num
\*******************************************************/
std::string Arithmetic::GetData() const
{
return m_num;
}
/*******************************************************\
函数: operator +
功能: 计算大数加法
输入: Arithmetic对象
输出: 无
返回: 2数之和
\*******************************************************/
Arithmetic operator + (Arithmetic& numa, Arithmetic& numb)
{
std::string strNuma = numa.GetData(), strNumb = numb.GetData();
Arithmetic result = numa.PlusMinus(strNuma, strNumb);
return result;
}
/*******************************************************\
函数: operator -
功能: 计算大数减法
输入: Arithmetic对象
输出: 无
返回: 2数之差
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -