//digit.cpp
#include <stdafx.h>
#include "digit.h"
#include <cmath>
CString LEGAL=_T("0123456789.+-*/()abcdefgho ,");
//////////////////////////////////////构造析构初始化函数////////////////////////////////
DIGIT::DIGIT()
{
Initialize();
}
DIGIT::DIGIT(CString myformula)
{
formula=myformula.MakeLower();
Initialize();
Error();
Part();
}
DIGIT::~DIGIT()
{
}
void DIGIT::InFormula(CString myformula)
{
formula=myformula.MakeLower();
Initialize();
Error();
Part();
}
///////////////////////////////////////输出值函数////////////////////////////////////////
double DIGIT::Result()
{
if(error)
{
return 0;
}
int index=0;
while(index<componentnum)
{
if(error!=0)
{
return 0;
}
if(component[index]==_T("-"))
{
if(component[index-1]==_T("("))
{
if(IsNum(component[index+1]))
{
Operate(_T("-")+component[index+1]);
index++;
}
else
{
error=10;
return 0;
}
}
else
{
Operate(component[index]);
}
}
else
{
Operate(component[index]);
}
index++;
}
double replace;
if(numstack.GetTop(replace))
{
return replace;
}
error=10;
return 0;
}
CString DIGIT::Result2()
{
if(error)
{
return _T("?");
}
return Dec2Other(Result(),2);
}
CString DIGIT::Result8()
{
if(error)
{
return _T("?");
}
return Dec2Other(Result(),8);
}
CString DIGIT::Result16()
{
if(error)
{
return _T("?");
}
return Dec2Other(Result(),16);
}
CString DIGIT::ResultF()
{
if(error)
{
return _T("?");
}
int index;
double temp=Result();
int intPart=int(temp);
double decPart=temp-intPart;
if(fabs(decPart)<1e-6)
{
CString intwords;
intwords.Format(_T("%d"),intPart);
return intwords;
}
double min=1;
double dectemp;
long inttemp;
long numerator,denominator;
for(index=1;index<100000;index++)
{
inttemp=int(decPart*index);
dectemp=decPart*index-inttemp;
if(dectemp<min)
{
numerator=inttemp;
denominator=index;
min=dectemp;
}
}
for(index=numerator;index>0;index--)
{
if(numerator%index==0 && denominator%index==0)
{
break;
}
}
numerator/=index;
denominator/=index;
numerator+=denominator*intPart;
CString str;
str.Format(_T("%ld/%ld"),numerator,denominator);
return str;
}
CString DIGIT::GetErrorStr()
{
switch(error)
{
case 1:
return _T("算式为空");
case 2:
return _T("算式中含有非法字符");
case 3:
return _T("算式左右括号不等");
case 4:
return _T("数字书写错误");
case 5:
return _T("除数不能为零");
case 6:
return _T("运算符放在表达式头");
case 7:
return _T("出现两个连续的运算符");
case 8:
return _T("运算符出现在表达式尾");
case 10:
return _T("算式格式不正确");
}
return _T("正确");
}
int DIGIT::GetErrorInt()
{
return error;
}
/////////////////////////////////////////实用辅助函数////////////////////////////////////////
double DIGIT::Other2Dec(CString other,int grade)
{
other.MakeLower();
char sign='+';
if(other[0]=='-')
{
sign='-';
other=other.Mid(1,other.GetLength()-1);
}
int pointpos=other.Find('.');
if(pointpos==-1)
{
pointpos=other.GetLength();
}
CString intPart=other.Mid(0,pointpos);
CString decPart=other.Mid(pointpos+1,other.GetLength()-pointpos-1);
double temp;
int index;
double store=0;
for(index=0;index<intPart.GetLength();index++)
{
temp=Char2Num(intPart[index]);
if(temp<grade)
{
store=store+temp*pow(double(grade),intPart.GetLength()-index-1);
}
}
for(index=1;index<=decPart.GetLength();index++)
{
temp=Char2Num(decPart[index-1]);
if(temp<grade)
{
store=store+temp*pow(double(grade),index*(-1));
}
}
if(sign=='-')
{
store=store*(-1);
}
return store;
}
CString DIGIT::Dec2Other(double dec,int grade)
{
int count;
wchar_t sign='+';
if(dec<0)
{
sign='-';
dec=dec*(-1);
}
int intpart=int(dec);
double decpart=dec-intpart;
count=0;
CString store=_T("");
while(intpart!=0)
{
store=store+Num2Char(intpart%grade);
intpart=intpart/grade;
count++;
}
store.MakeReverse();
store=store+_T(".");
count=0;
while(decpart>1e-10 && count<MAX_LENGTH-store.GetLength())
{
store=store+Num2Char(int(decpart*grade));
decpart=(decpart*grade)-int(decpart*grade);
count++;
}
if(sign=='-')
{
store=_T("-")+store;
}
if(store==_T("."))
{
store=_T("0");
}
else if(store[store.GetLength()-1]=='.')
{
store=store.Mid(0,store.GetLength()-1);
}
else if(store[0]=='.')
{
store=_T("0")+store;
}
return store;
}
///////////////////////////////////////主要操作函数////////////////////////////////////////
bool DIGIT::Part()
{
if(!error)
{
int count=0;
CString temp=_T("");
for(int index=0;index<formula.GetLength();index++)
{
if(formula[index]==' ' || formula[index]==',')
{
continue;
}
else if(formula[index]=='+' || formula[index]=='-' || formula[index]=='*' || formula[index]=='/' || formula[index]==')')
{
if(temp==_T(""))
{
if(formula[index]=='-')
{
component[count]=formula[index];
count++;
temp="";
}
else if(count>=1 && component[count-1]==")")
{
component[count]=formula[index];
count++;
temp="";
}
else
{
componentnum=0;
error=7;
return false;
}
}
else
{
component[count]=temp;
count++;
component[count]=formula[index];
count++;
temp=_T("");
}
}
else if(formula[index]=='(')
{
if(temp==_T(""))
{
component[count]=formula[index];
count++;
temp=_T("");
}
else
{
error=10;
componentnum=0;
return false;
}
}
else
{
temp=temp+formula[index];
}
if(index==formula.GetLength()-1)
{
if(temp!=_T(""))
{
component[count]=temp;
count++;
}
component[count]=_T("#");
count++;
componentnum=count;
}
}
return true;
}
return false;
}
double DIGIT::Calculate(wchar_t sign,double num1,double num2)
{
double result=0;
switch(sign)
{
case '+':
result=num1+num2;
break;
case '-':
result=num1-num2;
break;
case '*':
result=num1*num2;
break;
case '/':
if(fabs(num2)<1e-10)
{
error=5;
return 0;
}
result=num1/num2;
break;
}
return result;
}
void DIGIT::Operate(CString str)
{
double result;
wchar_t sign;
double num1,num2;
if(str==_T("("))
{
signstack.Push('(');
}
else if(str==_T("+") || str==_T("-"))
{
if(!signstack.GetTop(sign))
{
error=10;
return;
}
if(sign=='(' || sign=='#')
{
signstack.Push(str[0]);
}
else
{
do
{
if(!numstack.Pop(num1))
{
error=10;
return;
}
if(!numstack.Pop(num2))
{
error=10;
return;
}
if(!signstack.Pop(sign))
{
error=10;
return;
}
result=Calculate(sign,num2,num1);
numstack.Push(result);
signstack.GetTop(sign);
}while(!(sign=='(' || sign=='#'));
signstack.Push(str[0]);
}
}
else if(str==_T("*") || str==_T("/"))
{
if(!signstack.GetTop(sign))
{
error=10;
return;
}
if(sign=='*' || sign=='/')
{
do
{
if(!numstack.Pop(num1))
{
error=10;
return;
}
if(!numstack.Pop(num2))
{
error=10;
return;
}
if(!signstack.Pop(sign))
{
error=10;
return;
}
result=Calculate(sign,num2,num1);
numstack.Push(result);
signstack.GetTop(sign);
}while(sign=='*' || sign=='/');
signstack.Push(str[0]);
}
else
{
signstack.Push(str[0]);
用于C++的进制运算类
需积分: 0 92 浏览量
更新于2008-12-17
收藏 114KB RAR 举报
在C++编程中,进制转换是常见的操作,如十进制与二进制、八进制、十六进制之间的转换。"用于C++的进制运算类"提供了一个便捷的方式来处理这些运算,使得程序员无需手动编写繁琐的转换代码。这个类库可能包括了将整数或字符串形式的数字在不同进制间转换的功能,以及可能支持其他高级运算,比如进制的加减乘除。
标题中的"进制运算类"暗示了这个库的核心是一个类,我们称之为`Digit`,它封装了各种进制转换和运算的方法。下面是一些可能存在于`digit.h`和`digit.cpp`中的关键成员和方法:
1. **构造函数**:可能有一个接受十进制整数的构造函数,用于创建表示该数值的`Digit`对象。
2. **进制转换**:
- `toBinary()`: 返回对象表示的数值的二进制字符串。
- `toOctal()`: 返回对象表示的数值的八进制字符串。
- `toHexadecimal()`: 返回对象表示的数值的十六进制字符串。
3. **进制解析**:
- `fromBinary(const std::string &binary)`: 从二进制字符串创建一个`Digit`对象。
- `fromOctal(const std::string &octal)`: 从八进制字符串创建一个`Digit`对象。
- `fromHexadecimal(const std::string &hexadecimal)`: 从十六进制字符串创建一个`Digit`对象。
4. **进制运算**:
- `add(Digit other)`: 在当前进制下执行加法运算。
- `subtract(Digit other)`: 在当前进制下执行减法运算。
- `multiply(Digit other)`: 在当前进制下执行乘法运算。
- `divide(Digit other)`: 在当前进制下执行除法运算。
5. **其他辅助方法**:
- `getBase()`: 获取当前`Digit`对象所表示的数值的进制。
- `setBase(int base)`: 设置`Digit`对象的进制。
除了`Digit`类,`chainstack.h`和`node.h`可能定义了链栈(链式栈)的数据结构,这通常用于辅助进行进制转换,特别是在从其他进制到十进制的转换过程中。链栈是一种动态存储数据的结构,可以方便地实现后进先出(LIFO)的操作。
`DigitTestDlg.cpp`和`DigitTest.cpp`是测试代码,可能包含了使用`Digit`类的示例,用于验证类的功能是否正确。`stdafx.cpp`和`stdafx.h`是Visual Studio项目的标准预编译头文件,包含常用库和编译选项。
`DigitTest.exe`是可执行文件,是测试程序的成果,可以直接运行以查看`Digit`类的功能是否按预期工作。
这个类库提供了一种高效且易于使用的接口,用于在C++中进行各种进制的运算和转换,大大简化了开发者的工作,提高了代码的可读性和可维护性。通过这个类,用户能够轻松地在不同的数字系统之间进行计算,增强了C++程序的灵活性。