/*
功能:
1. 任意进制到十进制(其他任意进制认为是补码,即左起首位如果为1则被认为是补码)
2. 十进制到任意进制(负数则输出其补码形式)
3. 得到十进制数的Gray码
4. 得到Gray码对应的二进制编码
时间: 2002-7-3
注意: 当其他进制的进制数超过10时,使用A-Z这26个字母代替10-35这26个数.
所以实际上程序可以接受的输入在35(字母Z)以下.
*/
#include <iostream>
#include <sstream>
using namespace std;
//任意进制到十进制
bool Other2Dec(int &nDec , int nOther, int nBase );
bool Other2Dec(int &nDec , string strOther, int nBase );
//十进制到任意进制(负数采用补码形式)
bool Dec2Other(string &strOther,int nDec, int nBase);
//得到十进制数的Gray码
bool GetGrayCode(string &strGrayCode , int nDec);
//得到Gray码对应的二进制编码
bool GetBinCodeByGrayCode(string &strBinCode, const string &strGrayCode);
const int cnMinDecNum = static_cast<int>('0');
const int cnMaxDecNum = static_cast<int>('9');
const int cnMinHexNum = static_cast<int>('A');
const int cnMaxHexNum = static_cast<int>('Z');
void main()
{
//以下为测试代码:
int nDec ;
int nBase;
string strOther;
string strGrayCode;
string strBinCode;
cout<<"十进制\t格雷码\t格雷码->二进制\t十进制->二进制\t二进制->十进制"<<endl;
for(int i=-9;i<=0;i++)
{
GetGrayCode(strGrayCode,i);
GetBinCodeByGrayCode(strBinCode,strGrayCode);
Dec2Other(strOther,i,2);
Other2Dec(nDec,strOther,2);
cout<<i //十进制
<<"\t"<<strGrayCode //格雷码
<<"\t\t"<<strBinCode //格雷码->二进制
<<"\t"<<strOther //十进制->二进制
<<"\t\t"<<nDec //二进制->十进制
<<endl;
}
char ch;
cout<<"是否继续(y/n)?";
cin >> ch;
if (ch != 'y' && ch != 'Y')
goto ExitFunc;
cout <<"十进制转换到其他进制:"<<endl;
cout<<"输入要被转换的十进制的数和希望的进制数(base):";
cin>>nDec>> nBase;
Dec2Other(strOther,nDec,nBase);
cout<<"十进制数" <<nDec<<"转化为"<<nBase<<"进制数为"<<strOther<<endl<<endl;
cout<<"是否继续(y/n)?";
cin >> ch;
if (ch != 'y' && ch != 'Y')
goto ExitFunc;
cout<<"其他进制数转换到十进制数:"<<endl;
cout<<"输入要被转换的其他进制的数和进制数(base):";
cin>> strOther>> nBase;
if (Other2Dec(nDec , strOther,nBase))
cout <<nBase<<"进制数转换到十进制数为"<<nDec<<endl;
else
cout <<"转换失败!"<<endl;
ExitFunc:
cout<<"按任意键退出..."<<endl;
cin.get();
}
//----------------Other2Dec---------------
//功能:将其他进制的数转化为十进制
//参数:
// nDec : 返回的十进制数
// nOther: 其他进制数的值
// nBase : 其他进制数的进制
//返回值:
// true : 输入合法,操作成功
// false : 输入不合法,操作失败
bool Other2Dec(int &nDec, int nOther, int nBase =2 )
{
ostringstream ostrOther;
ostrOther << nOther;
string strOther;
strOther = ostrOther.str();
return Other2Dec(nDec, strOther,nBase);
}
//----------------Other2Dec---------------
//功能:将其他进制的数转化为十进制
//参数:
// nDec : 返回的十进制数
// nOther: 其他进制数的值
// nBase : 其他进制数的进制
//返回值:
// true : 输入合法,操作成功
// false : 输入不合法,操作失败
bool Other2Dec(int &nDec, string strOther, int nBase =2 )
{
int nLen = strOther.length();
if(nLen <=0)
return false;
if(nBase <=1 || nBase >=36)
{
cout<<"错误的进制的值,请输入2-35!"<<endl;
return false;
}
//补齐4的整数倍位数
while( strOther.length() % 4 != 0)
{
strOther = "0" + strOther;
}
nDec =0;
for(int i=0;i<nLen;i++)
{
char ch = strOther.at(i);
int nCh = static_cast<int>(ch);
if(nBase < 10)
{
if(nCh>= cnMinDecNum && nCh <= cnMaxDecNum)
nCh = nCh - cnMinDecNum + 0;
else
{
cout<<"---非法的输入!---"<<endl;
return false;
}
}
else
{
if( nCh >= cnMinHexNum && nCh <= cnMaxHexNum)
nCh = nCh - cnMinHexNum + 10;
else if(nCh>= cnMinDecNum && nCh <= cnMaxDecNum)
nCh = nCh - cnMinDecNum + 0 ;
else
{
cout<<"---非法的输入!---"<<endl;
return false;
}
}
nDec = nDec * nBase + nCh;
}
//如果以1开头,则表示是负数,由补码的定义,需要使用 nDec = -1 * (pow(2,n) - nDec);
if(strOther.at(0) == '1')
{
int nNum =1;
for(int j=0;j<strOther.length();j++)
{
nNum *= nBase;
}
nDec = -1 * (nNum - nDec);
}
return true;
}
//----------------Dec2Other---------------
//功能:将十进制数转化为其他进制的数
//参数:
// strOther : 返回的其他进制数字符串
// nDec : 其他进制数的值
// nBase : 其他进制数的进制
//返回值:
// true : 输入合法,操作成功
// false : 输入不合法,操作失败
bool Dec2Other(string &strOther,int nDec, int nBase =2)
{
if(nBase <=1 || nBase >=36)
{
cout<<"错误的进制的值,请输入2-35!"<<endl;
return false;
}
//当小于0时,下面将nDec用补码表示,
//即将nDec 变为: nDec = pow(2,n) + nDec;
//其中n为编码的维数,即nDec表示为有符号其它进制数时所需要的位数.
if (nDec < 0)
{
int nNum = nDec * -1;
int nDigit =0;
while(nNum >0)
{
nNum = nNum / nBase;
nDigit++;
}
int nDiv = nDigit / 4;
nDigit = (nDiv + 1) * 4;
nNum =1;
for(int i=0;i<nDigit;i++)
{
nNum *= nBase;
}
nDec = nNum + nDec;
}
ostringstream ostrOther;
int nResidual; //余数
do
{
nResidual = nDec % nBase;
nDec = nDec / nBase;
if(nBase >10 && nResidual >=10) //当进制大于10且余数大于10时
{
//使之输出A-Z的字母
nResidual = nResidual - 10 + cnMinHexNum;
char ch = static_cast<char>(nResidual);
ostrOther << ch;
}else{ //其余情况存入余数
ostrOther << nResidual ;
}
}while(nDec>0);
string strReverse = ostrOther.str();
//反转字符串,得到strOther
strOther = "";
for(int i=0;i<strReverse.length();i++)
strOther = strReverse.at(i) + strOther;
//补齐4的整数倍位数
while( strOther.length() % 4 != 0)
{
strOther = "0" + strOther;
}
return true;
}
//----------------GetGrayCode---------------
//功能: 得到十进制数的Gray码
//参数:
// strGrayCode : 得到的Gray码字符串
// nDec : 要转换的十进制数
//返回值:
// true : 输入合法,操作成功
// false : 输入不合法,操作失败
//说明:
// Gray码: G(i) 和 R(i)分别代表任意一位的格雷码和二进制数,则格雷码构成如下:
// G(4) = R(4)
// G(i) = R(i+1) XOR R(i)
bool GetGrayCode(string &strGrayCode , int nDec)
{
string strBin ;
Dec2Other(strBin,nDec,2);
ostringstream ostrGrayCode;
int nCur;
//左起第一个字符相同
//减去'0'对应的的整数值,得到真正代表的数字
int nFro = static_cast<int>(strBin.at(0)) - cnMinDecNum;
ostrGrayCode << nFro;
for(int i=1;i<strBin.length();i++)
{
//减去'0'对应的的整数值,得到真正代表的数字
nFro = static_cast<int>(strBin.at(i-1)) - cnMinDecNum;
//减去'0'对应的的整数值,得到真正代表的数字
nCur = static_cast<int>(strBin.at(i) ) - cnMinDecNum;
ostrGrayCode << ((nFro + nCur ) % 2); //按位异或
}
strGrayCode = ostrGrayCode.str();
return true;
}
//----------------GetBinCodeByGrayCode---------------
//功能: 得到Gray码对应的二进制编码
//参数:
// strBinCode : 得到的BCD编码字符串
// strGrayCode : Gray码字符串
//返回值:
// true : 输入合法,操作成功
// false : 输入不合法,操作失败
bool GetBinCodeByGrayCode(string &strBinCode, const string &strGrayCode)
{
ostringstream ostrBinCode;
int nCur;
//左起第一个字符相同
//减去'0'对应的的整数值,得到真正代表的数字
int nFro = static_cast<int>(strGrayCode.at(0)) - cnMinDecNum;
ostrBinCode << nFro;
strBinCode = ostrBinCode.str();
for(int i=1;i<strGrayCode.length();i++)
{
//减去'0'对应的的整数值,得到真正代表的数字
nFro = static_cast<int>(strBinCode.at(i-1)) - cnMinDecNum;
//减去'0'对应的的整数值,得到真正代表的数字
nCur = static_cast<int>(strGrayCode.at(i) ) - cnMinDecNum;
ostrBinCode << ((nFro + nCur) % 2 ); //按位异或
strBinCode = ostrBinCode.str();
}
return true;
}