📄 bignumclass.cpp
字号:
#include "stdafx.h"
#include "BignumClass.h"
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//构造函数
BignumClass::BignumClass( char *Char )
{
strcpy(str,Char) ;
}
//构造函数
BignumClass::BignumClass()
{
}
//析构函数
BignumClass::~BignumClass()
{
for(int i=0 ;i<100 ;i++)
str[i]='\0' ;
}
void BignumClass::translate_char()
{
head = NULL ;
for(int i = 0 ; i < strlen(str) ;)
{
pnew=(struct strArray *)malloc(sizeof(struct strArray)) ;//开辟新结点
//pnew=new struct strData ;
///////////////////////////////结点初始化/////////////////////////////////
if(head == NULL) { temp = head = pnew ; temp -> before = NULL ; } //是头结点
else //连结链表
{
pnew -> before = temp ;
temp=temp -> next = pnew ;
}
arrayToZero(temp->nArray );//数组初值都为0
temp -> cChar=' ' ;
temp -> next=NULL ;//它的下一个结点没东西
switch( str[i] )//对具体的字符以具体的处理
{//switch
case '+' :
temp -> nCharInt=1 ;//1表示是字符 0 是数字
temp -> cChar='+' ; //存相应的字符
i++ ;
break ;
case '-' : temp -> nCharInt=1 ; temp -> cChar='-' ; i++ ;break ;
case '*' : temp -> nCharInt=1 ; temp -> cChar='*' ; i++ ;break ;
case '/' : temp -> nCharInt=1 ; temp -> cChar='/' ; i++ ;break ;
case '!' : temp -> nCharInt=1 ; temp -> cChar='!' ; i++ ;break ;
case '(' : temp -> nCharInt=1 ; temp -> cChar='(' ; i++ ;break ;
case ')' : temp -> nCharInt=1 ; temp -> cChar=')' ; i++ ;break ;
case '^' : temp -> nCharInt=1 ; temp -> cChar='^' ; i++ ;break ;
case '[' : temp -> nCharInt=1 ; temp -> cChar='[' ; i++ ;break ;
case ']' : temp -> nCharInt=1 ; temp -> cChar=']' ; i++ ;break ;
case '=' : temp -> nCharInt=1 ; temp -> cChar='=' ; i++ ;break ;
case ',' : temp -> nCharInt=1 ; temp -> cChar=',' ; i++ ;break ;
case 'S' : temp -> nCharInt=1 ; temp -> cChar='S' ; i++ ;break ;//求和
case 's' : temp -> nCharInt=1 ; temp -> cChar='s' ; i++ ;break ;
case 'P' : temp -> nCharInt=1 ; temp -> cChar='P' ; i++ ;break ;//排列数
case 'p' : temp -> nCharInt=1 ; temp -> cChar='p' ; i++ ;break ;
case 'C' : temp -> nCharInt=1 ; temp -> cChar='C' ; i++ ;break ;//组合数
case 'c' : temp -> nCharInt=1 ; temp -> cChar='c' ; i++ ;break ;
case 'II': temp -> nCharInt=1 ; temp -> cChar='I' ; i=i+2 ;break ;//连乘
default :
/////////////////////处理 数字 字符串////////////////////
temp -> nCharInt=0 ;//它是要存放数字的
int top=0;
int nput = i;
while( str[nput] >= 48 && str[nput] <= 57||str[nput] == '.')//计算整数和小数的位数
{
if(str[nput] == '.') temp->nArray [0]=top;//0.7 top=1;;;有小数点了存一下整数的位数
top++;
nput++;
}
if(temp->nArray [0]==0)//没有.是一个整数
temp->nArray [0]=top;//存整数位数
else//有小数
temp->nArray [MAX-1]=top-temp->nArray [0]-1;//存小数位数
for(top=MAX*2/3-temp->nArray [0]+1;top<=MAX*2/3;top++)//把整数的各位按要求存入数组
{
temp->nArray [top]=str[i++]-48;//str[i++]-48 是由字符型的数字到int型的数字
}
if( temp->nArray [MAX-1]!=0)//有小数输入
{
i++;//跳过小数点
for(top=MAX*2/3+1;top<=MAX*2/3+temp->nArray [MAX-1];top++)//把小数的各位按要求存入数组
{
temp->nArray [top]=str[i++]-48;
}
}
if(temp->nArray [0]==1&&temp->nArray [MAX*2/3]==0)temp->nArray [0]=0;//0.7刚才整数位是1;
break;
}//end switch
}//end for
}
////////////////////////////以下是求值///////////////////////////////////
/////////////// 在这个类中我没有提供带()的四则混合运算 /////
////////////// ()[]只作公倍数公约数的标记和函数的参数 /////
//////////////////////////////////////////////////////////////////////
void BignumClass::slove()//求值函数
{
for( temp=head ; temp-> next !=NULL ; temp=temp-> next)
{ //for
if( temp-> cChar == '[')//[ ]是求最小公倍数的标记
{
common_multiple(temp->next);//求最小公倍数
copyNode(temp,temp->next);
pnew=temp;
while(pnew->cChar !=']'){pnew=pnew->next ;}
deleteNode(temp ,pnew->next );
}
if( temp-> cChar == '(')// left=temp ; // 记住左(的指针
{
if(temp->before ==NULL)// '( '是在第一位出现肯定是最大公约数
{
common_divisor(temp->next);
copyNode(temp,temp->next);
pnew=temp;
while(pnew->cChar !=')'){pnew=pnew->next ;}
deleteNode(temp ,pnew->next );
}
else
{ // int p_m;
switch(temp->before->cChar )
{//c (15,3)
case 'c' :
case 'C' :
int c_n;
int c_m;
c_m=arrToLong(temp->next ->next ->next-> nArray);
c_n=arrToLong(temp->next ->nArray);
permutation(temp->next ->nArray,c_n-c_m+1);//p(15,3)
permutation(temp->next ->next ->next-> nArray,1);//3!
arrDiv(temp->next ->nArray ,temp->next ->next ->next-> nArray );
copyNode(temp->before,temp->next);
deleteNode(temp->before ,temp->next->next->next->next->next );
temp=temp->before ;
break;//是求组合数了C(5,3)=10
case 's' :
case 'S' : break;//是求连加了s(1,10,i)=55即1+2+……+9+10
case 'I' : break;//是求连乘了I(1,10,i)=3628800即1*2*……*9*10
case 'p' :
case 'P' : //+p(5,3)- 只有p(5,3)
int p_m;
p_m=arrToLong(temp->next ->next ->next-> nArray);
permutation(temp->next ->nArray,p_m);
copyNode(temp->before,temp->next);
deleteNode(temp->before ,temp->next->next->next->next->next );
temp=temp->before ;
break;//是求排列数了P(5,3)=120
default : //是求最小公约数
break;
}
}
}//if (
} //end for
////////////////////////////现在没有括号了
for(temp=head ; temp->next !=NULL ; temp=temp->next )
{
switch(temp->cChar )
{
case '/':
if(temp->next->nArray [0]==0&& temp->next->nArray [MAX-1]==0);//MessageBox("除数为0");
else
{
arrDiv(temp->before->nArray ,temp->next->nArray );
deleteNode(temp->before ,temp->next ->next );
temp=temp->before;
}
break;
case '^':
long a;
if(temp->next ->nArray [MAX-1]!=0||temp->next ->nArray [0]==0) ::AfxMessageBox(" 我不想计算不是整数的乘方和0次幂!!!!");
a=arrToLong(temp->next ->nArray);
power(temp->before ->nArray,a);
deleteNode(temp->before ,temp->next ->next );//去掉几个结点 +22^5-化为+5153632-
temp=temp->before;
break;
case '!':
permutation(temp->before->nArray,1);
deleteNode(temp->before ,temp->next);//去掉几个结点+n!-化为+n-
temp=temp->before;
break;
case '*':
arrMul(temp->before->nArray ,temp->next->nArray );//乘后存在temp->before->nArray中
deleteNode(temp->before ,temp->next ->next );//去掉几个结点 +10*5-化为+50-
temp=temp->before;
break;
default :
break;
}//end swi
}//end for
//我没有为数组表示负数,故只能这样计算了
temp = head;
ArrayClass arr_positive;
ArrayClass arr_minus;
ArrayClass arr_tmp;
BignumClass s;
if(head->cChar =='-'){temp=temp->next ;s.copy (arr_minus.arr ,temp->nArray );}
else s.copy (arr_positive.arr ,head->nArray );
for(temp=temp->next ;temp->next !=NULL;temp=temp->next->next )//现在只剩下+ -运算了,对a-b-c-d+e+f用a+e+f-(b+c+d)来求
{//+22-23+43 or -44+6546-544
s.copy (arr_tmp.arr ,temp->next ->nArray );
if(temp->cChar =='-') arr_minus=arr_minus+arr_tmp;
if(temp->cChar =='+'){arr_positive=arr_positive+arr_tmp;}
s.arrayToZero(arr_tmp.arr);
}
arr_positive=arr_positive-arr_minus;
s.copy (head->nArray ,arr_positive.arr );
}
void BignumClass::arrayToZero(int narr[])
{
for(int i=0;i<MAX;i++)
narr[i]=0;
}
void BignumClass::common_divisor(struct strArray *first)//求最大公约数(3,6,5), 3
{
struct strArray *pt;
pt=first;
ArrayClass arrone;
arrone.arr [MAX*2/3]=1;//arrone.arr 就是1所成的数组
ArrayClass arrtop;
ArrayClass arrmin;
ArrayClass arrA(first->nArray );//第一个数
ArrayClass arrB(first->next ->next ->nArray );//第二个数
while(1)
{//3,6
arrone.compare(pt->nArray ,pt->next ->next ->nArray )==0?
copy(arrmin.arr ,pt->nArray):copy(arrmin.arr ,pt->next ->next ->nArray);//3,4
arrtop = arrmin;
while(1)
{
arrtop=arrtop-arrone;
if((arrA%arrtop)==0&&(arrB%arrtop)==0)break;
}
if((arrtop.arr [0]==1&&arrtop.arr [MAX*2/3]==1)||pt->next ->next ->next ->cChar ==')')
{///arrtop 是1或者没有再要算的了
copy(first->nArray ,arrtop.arr );
return;
}
else
{//还要继续
pt=pt->next ->next ;////pt----->6
copy(pt->nArray ,arrtop.arr );//(3,6)=3--->6 --> (3,5)
copy(arrA.arr,pt->nArray);
copy(arrB.arr,pt->next ->next ->nArray);
}
}
}
void BignumClass::common_multiple(struct strArray *first)//求最小公倍数
{//[3,5,6]
struct strArray *pt;
pt=first;
ArrayClass arrone;
arrone.arr [MAX*2/3]=1;//arrone.arr 就是1所成的数组
ArrayClass arrtop;
ArrayClass arrmax;
ArrayClass arrA(first->nArray );//第一个数3
ArrayClass arrB(first->next ->next ->nArray );//第二个数5
while(1)
{//3,5
arrone.compare(pt->nArray ,pt->next ->next ->nArray )==1?
copy(arrmax.arr ,pt->nArray):copy(arrmax.arr ,pt->next ->next ->nArray);//3,4
arrtop = arrmax;
while(1)
{
if((arrtop%arrA)==0&&(arrtop%arrB)==0) break;
arrtop=arrtop+arrone;
}
if(pt->next ->next ->next ->cChar ==']')
{///arrtop 没有再要算的了
copy(first->nArray ,arrtop.arr );
return;
}
else
{//还要继续
pt=pt->next ->next ;////pt----->5
copy(pt->nArray ,arrtop.arr );//[3,5]=15--->5 --> [15,6]
copy(arrA.arr,pt->nArray);
copy(arrB.arr,pt->next ->next ->nArray);
}
}
}
void BignumClass::redressal(int arr1[])//调整数组,使每位上数字不大于10
{
int xx;
for(int t=MAX-2;t>=1;t--)
{
if(arr1[t]==0)continue ;
xx=arr1[t]; //324
arr1[t]=xx%10; //arr1[t]=4=324%10
xx=xx/10; //xx=32=324/10
arr1[t-1]=arr1[t-1]+xx;
}
for(t=1;arr1[t]==0&&t<=MAX*2/3;t++);
getDigit(arr1);
// arr1[0]=MAX*2/3-t+1;
}
int BignumClass::zero(int arrdividend[])//被除数是否为0了
{
for(int t=1;t<MAX-1;t++)
{
if(arrdividend[t]!=0) return 0;
}
if(t==MAX-1)return 1;
}
void BignumClass::getDigit(int narr[])//得到长整数的整数和小数位数
{
for(int t=1;t<=MAX*2/3;t++)
if(narr[t]!=0)break;
narr[0]=MAX*2/3-t+1;
for(t=MAX-2;t>=MAX*2/3+1;t--)
if(narr[t]!=0)break;
narr[MAX-1]=t-MAX*2/3;
}
void BignumClass::copy(int keep[],int end[])//把end copy 给keep
{
for(int t=0;t<MAX;t++)
keep[t] = end[t];
}
void BignumClass::deleteNode(struct strArray *first,struct strArray *second)//删除结点
{
first->next =second;
second->before =first;
}
void BignumClass::power(int arr[],long b)//计算arr^b;
{
if((arr[0]-1)*b+1>MAX*2/3){::AfxMessageBox("你要我算的位数太大了!");return;}//error 估算肯定越位
ArrayClass arr1(arr);
ArrayClass arr2;
arr2=arr1;
for(int t=2;t<=b;t++)
{ arr2=arr1*arr2;
if(arr2.arr [1]!=0||arr2.arr [2]!=0||arr2.arr [3]!=0) {::AfxMessageBox("你要我算的位数太大了!");return;}
}
copy(arr,arr2.arr );
}
long BignumClass::arrToLong(int arr[])//把arr化为long
{ long nlong=0;
int k=1;
for(int t=MAX*2/3;t>MAX*2/3-arr[0];t--)
{
nlong=nlong+arr[t]*k;
k=k*10;
}
return nlong;
}
void BignumClass::permutation(int narr[],int m)//p(n,m)求排列
{
int n=arrToLong(narr);
if((n-m-1)*narr[MAX-1]>MAX*2/3) {::AfxMessageBox("你要我算的位数太大了!");return;}//error 估算可能越位
ArrayClass arr1(narr);
ArrayClass arrtmp;
ArrayClass arrone;
arrone.arr [MAX*2/3]=1;//arrone.arr 就是1所成的数组
arrtmp=arr1;
arr1=arr1-arrone;//n=n-1
for(long t=n-1;t>=m;t--)
{
arrtmp=arrtmp*arr1;
if(arrtmp.arr [1]!=0||arrtmp.arr [2]!=0||arrtmp.arr [3]!=0) {::AfxMessageBox("你要我算的位数太大了!");return;}//error 估算可能越位
arr1=arr1-arrone;
}
copy(narr,arrtmp.arr );
}
void BignumClass::copyNode(struct strArray *keep,struct strArray *tmp)//结点拷贝tmp的内容给keep
{
keep->cChar =tmp->cChar ;
copy( keep->nArray ,tmp->nArray );
keep->nCharInt =tmp->nCharInt ;
}
void BignumClass::arrMul(int arrfir[],int arrsec[])//两处数组相乘
{
ArrayClass arr1(arrfir);
ArrayClass arr2(arrsec);
arr1=arr1*arr2;
copy(arrfir,arr1.arr );
}
void BignumClass::arrDiv(int arrfir[],int arrsec[])//两处数组相除
{
ArrayClass arr1(arrfir);
ArrayClass arr2(arrsec);
arr1=arr1/arr2;
copy(arrfir,arr1.arr );
}
//如果p(n,m),n!,a^b 中n,m,b,太大就不要运算了
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -