/**************************************************** * Elementary operations on Polynomials in C++ * * ------------------------------------------------- * * Ref.: "Mathématiques en Turbo-Pascal by M. Ducamp * * and A. Reverchon (vol 2), Eyrolles, Paris, 1988" * * [BIBLI 05]. * * ------------------------------------------------- * * * * C++ version by J-P Moreau, Paris. * * (www.jpmoreau.fr) * ****************************************************/ #include #include #include #include #include "polynoms.h" // return greater common divisor of two long integers long GCD(long a, long b) { double r; a=labs(a); b=labs(b); if (a==0 || b==0) return 1; if (a0); return a; } // put a string into a number. Valid strings: 5.56874 or 15/187 or 255 bool SetNumber(ar_number *n, char *ch) { unsigned int i,ipos; long r; bool is_fract=FALSE; char temp[20]; n->is_real=FALSE; for (i=0; iis_real=TRUE; //detect a point in string ch if (n->is_real) n->value=atof(ch); else { for (i=0; ip=atol(temp); n->q=atol(&ch[ipos+1]); //simplify p and q ? r=GCD(n->p,n->q); n->p/=r; n->q/=r; n->value=(double) n->p/n->q; } else { // case of an integer n->value=atof(ch); n->p=atol(ch); n->q=1; } } return TRUE; } //Add two numbers of type ar_number (double, integer or fractional) bool AddNumber(ar_number x, ar_number y, ar_number *z) { long s; bool negative; z->is_real=(x.is_real || y.is_real); z->value=x.value+y.value; if (x.value==0) *z=y; else if (y.value==0) *z=x; else { if (labs(x.p) > AR_MAXLONG || labs(x.q) > AR_MAXLONG || labs(y.p) > AR_MAXLONG || labs(y.q) > AR_MAXLONG) z->is_real = TRUE; if (!z->is_real) { s=GCD(x.q,y.q); z->p=x.p*y.q+x.q*y.p; z->q=x.q*y.q; negative=(z->p*z->q<0); z->p=labs(z->p) /s; z->q=labs(z->q) /s; if (negative) z->p=-z->p; } } return TRUE; } //Multiply two numbers of type ar_number (double, integer or fractional) bool MultNumber(ar_number x, ar_number y, ar_number *z) { long s; bool negative; z->is_real=(x.is_real || y.is_real); z->value=x.value * y.value; if (z->value==0) { z->p=0; z->q=1; } else { if (labs(x.p) > AR_MAXLONG || labs(x.q) > AR_MAXLONG || labs(y.p) > AR_MAXLONG || labs(y.q) > AR_MAXLONG) z->is_real = TRUE; if (!z->is_real) { z->p=x.p*y.p; z->q=x.q*y.q; s=GCD(z->p,z->q); negative=(z->p*z->q<0); z->p=labs(z->p) /s; z->q=labs(z->q) /s; if (negative) z->p=-z->p; } } return TRUE; } //Divide two numbers of type ar_number (double, integer or fractional) bool DivNumber(ar_number x, ar_number y, ar_number *z) { long s; bool negative; if (y.value==0) return FALSE; z->is_real=(x.is_real || y.is_real); if (labs(x.p) > AR_MAXLONG || labs(x.q) > AR_MAXLONG || labs(y.p) > AR_MAXLONG || labs(y.q) > AR_MAXLONG) z->is_real = TRUE; if (!z->is_real) { z->p=x.p*y.q; z->q=x.q*y.p; s=GCD(z->p,z->q); negative=(z->p*z->q<0); z->p=labs(z->p) /s; z->q=labs(z->q) /s; if (negative) z->p=-z->p; } z->value=x.value/y.value; return TRUE; } //read from screen a number of type ar_number (double, integer or fractional) void ReadNumber(char *tx, ar_number *n) { char ch[20]; int i; for (i=1; i<4; i++) { printf(" %s",tx); scanf("%s",ch); if (SetNumber(n,ch)) return; //MessageBeep(0); } } //write to screen a number of type ar_number (double, integer or fractional) void WriteNumber(ar_number n) { if (n.value>0) printf("+ "); else printf("- "); if (n.is_real) printf("%f",fabs(n.value)); else { printf("%d",labs(n.p)); if (labs(n.q)!=1) printf("/%d",labs(n.q)); } } //function called by EnterPolynom() //Analysis of elementary monom, example: +5.25x3 or +5x3 or 5/3x3 bool ExtractMonom(char *ch, ar_polynom *p) { ar_number coeff; char chn[200]; int degree,xpos,sppos,signe; unsigned int i; //eliminate blank spaces while (ch[0]==' ') strcpy(ch,&ch[1]); if (ch[0]=='\0') return FALSE; signe=(ch[0]=='-') ? -1 : 1; if (ch[0]=='+' || ch[0]=='-') if (ch[1]) strcpy(ch,&ch[1]); while (ch[0]==' ') strcpy(ch, &ch[1]); if (ch[0]=='\0') return FALSE; //seek X characters xpos=-1; for (i=0; i<=strlen(ch); i++) if (ch[i]=='X') {xpos=i; break;} if (xpos<0) { degree=0; if (!SetNumber(&coeff,ch)) return FALSE; ch[0]='\0'; } else { if (xpos==0) { strncpy(chn,"1",1); chn[1]='\0'; } else { strncpy(chn,ch,xpos); chn[xpos]='\0'; } if (!SetNumber(&coeff,chn)) return FALSE; //seek a blank space sppos=-1; for (i=0; i<=strlen(ch); i++) if (ch[i]==' ') {sppos=i; break;} if (sppos<0) sppos=strlen(ch); if (xpos==sppos-1) degree=1; else { strncpy(chn, &ch[xpos+1], sppos-xpos-1); chn[sppos-xpos-1]='\0'; degree=atoi(chn); if (degree > AR_MAXPOL) return FALSE; } if (sppos >= strlen(ch)) strcpy(ch,""); else strcpy(ch, &ch[sppos+1]); } if (signe==-1) { coeff.p = -coeff.p; coeff.value = -coeff.value; } if (!AddNumber(coeff, p->coeff[degree],&p->coeff[degree])) return FALSE; if (degree > p->degree) p->degree=degree; return TRUE; } // ExtractMonom // convert a valid string into a polynomial of type ar_polynom. // Example of valid string: X5 +3/5X4 -12X2 +8X -1/4 // tx is a prompting message, example: Enter polynomial P(x): // Note that a blank space is required between monomes. bool EnterPolynom(char *tx, ar_polynom *p) { int i; char ch[200]; for (i=1; i<4; i++) { printf("%s",tx); memset ((char *) p, 0, sizeof(ar_polynom)); gets(ch); strupr(ch); while ((ch[0]!='\0') && (ExtractMonom(ch,p))); if (ch[0]=='\0') return TRUE; //MessageBeep(0); } printf("\n"); return FALSE; } // This procedure displays to screen the symbolic // representation of a polynom of type ar_polynom void DisplayPolynom(ar_polynom *p) { int i; long lp,lq; char tmp[10]; printf("\n "); if (p->degree==0 && p->coeff[0].value==0) printf("0"); else for (i=p->degree; i>=0; i--) if (fabs(p->coeff[i].value) > AR_SMALL) { printf((p->coeff[i].value<0) ? "-" : "+"); if (p->coeff[i].is_real) printf("%10.6f",fabs(p->coeff[i].value)); else { lp=labs(p->coeff[i].p); lq=labs(p->coeff[i].q); if (lp!=1 || lq!=1 || i==0) printf("%d",lp); if (lq!=1) printf("/%d",lq); } sprintf(tmp," X%d ",i); printf("%s", (i>1) ? tmp : (i>0) ? " X " : " "); } printf("\n"); } // return the value y of a polynomial of type ar_polynom for argument=x // x and y are of type ar_number (double, integer or fractional) bool EvaluatePolynom(ar_polynom *p, ar_number *x, ar_number *y) { int i; if (p->degree > AR_MAXPOL) return FALSE; SetNumber(y, "0"); for (i=0; i<=p->degree; i++) { if (!MultNumber(*y,*x,y)) return FALSE; if (!AddNumber(*y,p->coeff[p->degree-i],y)) return FALSE; } return TRUE; } // end of file polynom.cpp