00001
00002
00003
00004
00005 #include "BigNum.h"
00006 #include <Math.h>
00007 #include <String.h>
00008 #include <stdlib.h>
00009
00010
00011
00012
00013 long BigNum::A_Numero()
00014 {
00015 PNDoble Cte=0;
00016 int i,err=0;
00017 TMayor aux=0;
00018 for (i=0,err=Lis->MoverCte(Cte,'p');(err==0);i++,err=Lis->MoverCte(Cte,'s'))
00019 aux+=TMayor(Lis->ObtCte(Cte)*pow(double(MAXBASE),i));
00020
00021 return(signo*aux);
00022 }
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 BigNum::BigNum(int Nro)
00033 {
00034 int num=Nro;
00035 Lis = new LDoble;
00036 if (num<0) {
00037 signo=-1;
00038 num=abs(num); }
00039 else
00040 signo=1;
00041 TDato n;
00042 PNDoble Cte=0;
00043
00044 if (num!=0)
00045
00046 {
00047 do {
00048 n=num % MAXBASE;
00049 num=num / MAXBASE;
00050 Lis->InsDespues(Cte,n); }
00051 while (num);
00052 }
00053 }
00054 BigNum::BigNum(unsigned short int a[],int cant,char sign) {
00055 int i;
00056 Lis = new LDoble;
00057 PNDoble Cte=0;
00058 for (i=0;i<cant;i++)
00059 Lis->InsDespues(Cte,a[i]);
00060 signo=sign;
00061 }
00062 BigNum::BigNum()
00063 {
00064 Lis = new LDoble;
00065 signo=1;
00066 }
00067
00068 BigNum::BigNum(char *s)
00069 {
00070 char *p;
00071 int i;
00072 int neg=0;
00073 unsigned long int sum;
00074 Lis = new LDoble;
00075 p=s;
00076 if (*p=='-') {
00077 neg=1;
00078 p++;}
00079 signo=1;
00080 do {
00081 for(i=0,sum=0;((*p) && (i<9));i++,p++)
00082 sum=sum*10+(*p-'0');
00083 (*this)*=pow(double(10),i);
00084 (*this)+=sum; }
00085 while (*p);
00086 if (neg)
00087 signo=-1;
00088 }
00089 ostream& operator << (ostream& s, const BigNum & m) {
00090
00091 char cad[1000000];
00092 char cadaux[11];
00093 char* pcad;
00094 int lenaux;
00095 int neg=0;
00096 int i;
00097 BigNum aux(m);
00098 BigNum billon=1000000000,resto;
00099
00100 cin.get();
00101
00102 if (aux.signo==-1) {
00103 neg=1;
00104 aux.signo=1;
00105 }
00106 cad[999999]='\0';
00107 pcad=cad + 999998;
00108 *pcad = 0;
00109 s<<endl<<"Hasta aqui todo bien[while]"<<endl;
00110 cin.get();
00111 while (aux!=0) {
00112 resto=aux % billon;
00113 aux/=billon;
00114 _ltoa(resto.A_Numero(),cadaux,10);
00115 lenaux = strlen(cadaux);
00116 for (i=1; i<=lenaux; i++) {
00117 pcad--;
00118 *pcad = cadaux[lenaux-i];
00119 }
00120 for (; i<=9; i++) {
00121 pcad--;
00122 *pcad = '0';
00123 }
00124
00125
00126
00127 }
00128
00129 cin.get();
00130 pcad += 9-lenaux;
00131 if (!cad[0]) {
00132 cad[0]='\0';
00133 cad[1]='\0';
00134 }
00135
00136 cin.get();
00137
00138 if(neg) s <<'-'<< pcad;
00139 else s << pcad;
00140
00141 cin.get();
00142 return(s);
00143 }
00144
00145 BigNum::BigNum(const BigNum& a)
00146 {
00147
00148 Lis=a.Lis;
00149 Lis->CantRefs++;
00150 signo=a.signo;
00151 }
00152
00153 BigNum::~BigNum()
00154 {
00155
00156 if (Lis->CantRefs==1)
00157 delete Lis;
00158 else
00159 Lis->CantRefs--;
00160 }
00161
00162
00163 void BigNum::copiar(const BigNum& a)
00164 {
00165 int err;
00166 PNDoble Cte=0, CteA=0;
00167
00168 signo=a.signo;
00169 for (err=a.Lis->MoverCte(CteA, 'p');(!err);err=a.Lis->MoverCte(CteA, 's'))
00170 Lis->InsDespues(Cte,a.Lis->ObtCte(CteA));
00171 }
00172
00173 int BigNum::operator ==(const BigNum & a) const
00174 {
00175 PNDoble Cte=0, CteA=0;
00176 int err=Lis->MoverCte(Cte,'p'),err_a=a.Lis->MoverCte(CteA,'p');
00177 TDato cif,cif_a;
00178 if ((Lis->CantElem()==a.Lis->CantElem()) && (signo==a.signo)) {
00179 while (!err) {
00180 cif=Lis->ObtCte(Cte);
00181 cif_a=a.Lis->ObtCte(CteA);
00182 if (cif!=cif_a)
00183 return(0);
00184 err=Lis->MoverCte(Cte,'s');
00185 a.Lis->MoverCte(CteA,'s');}
00186 return(1);}
00187 else
00188 return(0);
00189 }
00190
00191 int BigNum::operator !=(const BigNum & a) const
00192 {
00193 return(!(*this==a));
00194 }
00195
00196 int BigNum::operator >(const BigNum & a) const
00197 {
00198 PNDoble Cte=0, CteA=0;
00199 if (signo!=a.signo)
00200 return((signo>a.signo));
00201 if (Lis->CantElem()==a.Lis->CantElem()) {
00202 int err=Lis->MoverCte(Cte,'u'),err_a=a.Lis->MoverCte(CteA,'u');
00203 TDato cif,cif_a;
00204 while (!err) {
00205 cif=Lis->ObtCte(Cte);
00206 cif_a=a.Lis->ObtCte(CteA);
00207 if (cif!=cif_a)
00208 return((cif>cif_a));
00209 err=Lis->MoverCte(Cte,'a');
00210 a.Lis->MoverCte(CteA,'a');}
00211 return(0);}
00212 else
00213 return((Lis->CantElem()>a.Lis->CantElem()));
00214 }
00215
00216 int BigNum::operator <(const BigNum & a) const
00217 {
00218 PNDoble Cte=0, CteA=0;
00219 if (signo!=a.signo)
00220 return((signo<a.signo));
00221 if (Lis->CantElem()==a.Lis->CantElem()) {
00222 int err=Lis->MoverCte(Cte,'u'),err_a=a.Lis->MoverCte(CteA,'u');
00223 TDato cif,cif_a;
00224 while (!err) {
00225 cif=Lis->ObtCte(Cte);
00226 cif_a=a.Lis->ObtCte(CteA);
00227 if (cif!=cif_a)
00228 return((cif<cif_a));
00229 err=Lis->MoverCte(Cte,'a');
00230 a.Lis->MoverCte(CteA,'a');}
00231 return(0);}
00232 else
00233 return((Lis->CantElem()<a.Lis->CantElem()));
00234 }
00235
00236 int BigNum::operator >=(const BigNum & a) const
00237 {
00238 return(!(*this<a));
00239 }
00240
00241 int BigNum::operator <=(const BigNum & a) const
00242 {
00243 return(!(*this>a));
00244 }
00245
00246 BigNum& BigNum::operator = (const BigNum & a)
00247 {
00248
00249
00250
00251
00252
00253
00254 Lis->Vaciar();
00255 copiar(a);
00256 return(*this);
00257
00258 }
00259
00260
00261 BigNum operator + (const BigNum & a, const BigNum & b)
00262 {
00263 BigNum r;
00264 PNDoble CteA, CteB, Cte=0;
00265
00266
00267
00268
00269
00270 if (a.signo!=b.signo) {
00271 if (a.signo==-1) {
00272 const_cast<BigNum&>(a).signo=1;
00273 r=b-a;
00274 const_cast<BigNum&>(a).signo=-1;}
00275 else {
00276 const_cast<BigNum&>(b).signo=1;
00277 r=a-b;
00278 const_cast<BigNum&>(b).signo=-1;}
00279 return(r);
00280 }
00281 else {
00282 int err_a=a.Lis->MoverCte(CteA,'p'),err_b=b.Lis->MoverCte(CteB,'p');
00283 TDato cif_a,cif_b;
00284 TDato pongo,mellevo=0;
00285 TMayor aux;
00286 while (!(err_a && err_b)) {
00287 if (err_a)
00288 cif_a=0;
00289 else
00290 cif_a=a.Lis->ObtCte(CteA);
00291 if (err_b)
00292 cif_b=0;
00293 else
00294 cif_b=b.Lis->ObtCte(CteB);
00295 aux=cif_a+cif_b+mellevo;
00296 pongo=aux % MAXBASE;
00297 mellevo=aux / MAXBASE;
00298 r.Lis->InsDespues(Cte,pongo);
00299 err_a=a.Lis->MoverCte(CteA,'s');
00300 err_b=b.Lis->MoverCte(CteB,'s');
00301 }
00302 if (mellevo)
00303 r.Lis->InsDespues(Cte,mellevo);
00304 r.signo=a.signo;
00305 return(r);
00306 }
00307 }
00308
00309
00310 BigNum operator - (const BigNum & a, const BigNum & b)
00311 {
00312 PNDoble CteA, CteB, Cte=0;
00313 BigNum r;
00314
00315
00316 if (a.signo!=b.signo) {
00317 if (b.signo==-1) {
00318 const_cast<BigNum&>(b).signo=1;
00319 r=a+b;
00320 const_cast<BigNum&>(b).signo=-1;}
00321 else {
00322 const_cast<BigNum&>(b).signo=-1;
00323 r=a+b;
00324 const_cast<BigNum&>(b).signo=1;}
00325 return(r);}
00326 else
00327 if (a.signo==-1){
00328 const_cast<BigNum&>(a).signo=1;
00329 const_cast<BigNum&>(b).signo=1;
00330 r=b-a;
00331 const_cast<BigNum&>(a).signo=-1;
00332 const_cast<BigNum&>(b).signo=-1;
00333 return(r);}
00334
00335 if (a<b) {
00336 r=b-a;
00337 r.signo*=-1;
00338 return(r);}
00339 int err_a=a.Lis->MoverCte(CteA,'p'),err_b=b.Lis->MoverCte(CteB,'p');
00340 TDato cif_a,cif_b;
00341 TDato pongo,mellevo=0;
00342 int cont=0,i;
00343 signed long aux;
00344 while (!(err_a)) {
00345 cif_a=a.Lis->ObtCte(CteA);
00346 if (err_b)
00347 cif_b=0;
00348 else
00349 cif_b=b.Lis->ObtCte(CteB);
00350 aux=cif_a-cif_b-mellevo;
00351 if (aux<0) {
00352 pongo=aux+MAXBASE;
00353 mellevo=1;}
00354 else {
00355 pongo=aux;
00356 mellevo=0;}
00357 if (pongo==0)
00358 cont++;
00359 else {
00360 for(i=1;i<=cont;i++)
00361 r.Lis->InsDespues(Cte,0);
00362 cont=0;
00363 r.Lis->InsDespues(Cte,pongo);}
00364 err_a=a.Lis->MoverCte(CteA,'s');
00365 err_b=b.Lis->MoverCte(CteB,'s');}
00366 return(r);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 BigNum operator * (const BigNum & a, const BigNum & b)
00378 {
00379 BigNum r;
00380
00381
00382
00383 PNDoble CteA, CteB, Cte=0;
00384 r.signo=a.signo*b.signo;
00385 int err_b,err_a,err=1;
00386 int i,comienzo=0;
00387 TMayor aux;
00388 TDato mellevo=0,mellevo2=0;
00389 TMayor cif;
00390 for (err_b=b.Lis->MoverCte(CteB,'p');(!err_b);err_b=b.Lis->MoverCte(CteB,'s'),comienzo++) {
00391 for (i=0,err=r.Lis->MoverCte(Cte,'p');i<comienzo;i++)
00392 err=r.Lis->MoverCte(Cte,'s');
00393 for (err_a=a.Lis->MoverCte(CteA,'p');(!err_a);err_a=a.Lis->MoverCte(CteA,'s')) {
00394 aux = b.Lis->ObtCte(CteB) * a.Lis->ObtCte(CteA) + mellevo;
00395 mellevo=aux / MAXBASE;
00396 if (err) {
00397 cif=aux % MAXBASE + mellevo2;
00398 mellevo2=cif / MAXBASE;
00399 r.Lis->InsDespues(Cte,cif % MAXBASE);}
00400 else {
00401 cif=r.Lis->ObtCte(Cte) + aux % MAXBASE + mellevo2;
00402 mellevo2= cif / MAXBASE;
00403 r.Lis->ModifCte(Cte,cif % MAXBASE);
00404 err=r.Lis->MoverCte(Cte,'s');}
00405 }
00406 if ((mellevo) || (mellevo2))
00407 r.Lis->InsDespues(Cte,mellevo+mellevo2);
00408 mellevo=mellevo2=0;
00409 }
00410 return(r);
00411 }
00412 BigNum operator / (const BigNum & a, const BigNum & b)
00413 {
00414 double signdivi=0, signresto;
00415 signed char signoa=a.signo,signob=b.signo;
00416 PNDoble CteA, CteB;
00417 PNDoble CteResto = 0, CteCociente = 0;
00418 TDato factor;
00419 BigNum cociente,resto;
00420 BigNum aux;
00421 int err,i,sale=0;
00422 int cantcif=0;
00423 const_cast<BigNum&>(a).signo=const_cast<BigNum&>(b).signo=resto.signo=cociente.signo=1;
00424
00425 if (b.Lis->CantElem()<2)
00426 i=b.Lis->CantElem();
00427 else
00428 i=2;
00429 for(err=b.Lis->MoverCte(CteB,'u');(!err) && (i);i--,err=b.Lis->MoverCte(CteB,'a')) {
00430 cantcif++;
00431 signdivi+=pow(double(MAXBASE),i-1) * b.Lis->ObtCte(CteB);}
00432 if (cantcif==0)
00433 return(0);
00434 for(err=a.Lis->MoverCte(CteA,'u');(!err);err=a.Lis->MoverCte(CteA,'a')) {
00435 resto.Lis->MoverCte(CteResto,'p');
00436 resto.Lis->InsAntes(CteResto,a.Lis->ObtCte(CteA));
00437 if (resto<b) {
00438 if (cociente.Lis->CantElem())
00439 cociente.Lis->InsAntes(CteCociente,0);}
00440 else {
00441 if (resto.Lis->CantElem()>b.Lis->CantElem())
00442 i=cantcif+1;
00443 else
00444 i=cantcif;
00445 signresto=0;
00446 for(err=resto.Lis->MoverCte(CteResto,'u');(!err) && (i);i--,err=resto.Lis->MoverCte(CteResto,'a'))
00447 signresto+=pow(double(MAXBASE),i-1) * resto.Lis->ObtCte(CteResto);
00448 factor=signresto/signdivi;
00449 do {
00450 aux=factor * b;
00451 if (aux>resto)
00452 factor--;
00453 else
00454 sale=1;}
00455 while (!sale);
00456 resto-=aux;
00457 cociente.Lis->InsAntes(CteCociente,factor);
00458 }
00459 }
00460 cociente.signo=signoa * signob;
00461 return(cociente);
00462 }
00463
00464 BigNum operator % (const BigNum & a, const BigNum & b)
00465 {
00466 double signdivi=0, signresto;
00467 signed char signoa=a.signo,signob=b.signo;
00468 PNDoble CteA, CteB;
00469 PNDoble CteResto = 0, CteCociente = 0;
00470 TDato factor;
00471 BigNum cociente,resto;
00472 BigNum aux;
00473 int err,i,sale=0;
00474 int cantcif=0;
00475 const_cast<BigNum&>(a).signo=const_cast<BigNum&>(b).signo=resto.signo=cociente.signo=1;
00476
00477 if (b.Lis->CantElem()<2)
00478 i=b.Lis->CantElem();
00479 else
00480 i=2;
00481 for(err=b.Lis->MoverCte(CteB,'u');(!err) && (i);i--,err=b.Lis->MoverCte(CteB,'a')) {
00482 cantcif++;
00483 signdivi+=pow(double(MAXBASE),i-1) * b.Lis->ObtCte(CteB);}
00484 if (cantcif==0)
00485 return(0);
00486 for(err=a.Lis->MoverCte(CteA,'u');(!err);err=a.Lis->MoverCte(CteA,'a')) {
00487 resto.Lis->MoverCte(CteResto,'p');
00488 resto.Lis->InsAntes(CteResto,a.Lis->ObtCte(CteA));
00489 if (resto<b) {
00490 if (cociente.Lis->CantElem())
00491 cociente.Lis->InsAntes(CteCociente, 0);}
00492 else {
00493 if (resto.Lis->CantElem()>b.Lis->CantElem())
00494 i=cantcif+1;
00495 else
00496 i=cantcif;
00497 signresto=0;
00498 for(err=resto.Lis->MoverCte(CteResto,'u');(!err) && (i);i--,err=resto.Lis->MoverCte(CteResto,'a'))
00499 signresto+=pow(double(MAXBASE),i-1) * resto.Lis->ObtCte(CteResto);
00500 factor=signresto/signdivi;
00501 do {
00502 aux=factor * b;
00503 if (aux>resto)
00504 factor--;
00505 else
00506 sale=1;}
00507 while (!sale);
00508 resto-=aux;
00509 cociente.Lis->InsAntes(CteCociente,factor);
00510 }
00511 }
00512 resto.signo=signoa;
00513 return(resto);
00514 }
00515
00516
00517
00518 BigNum& BigNum::operator++()
00519 {
00520
00521 PNDoble Cte;
00522
00523 if (signo==-1) {
00524 BigNum a;
00525 signo=1;
00526 (*this)--;
00527 if (!Lis->Vacia())
00528 signo=-1;}
00529 else {
00530 TDato cif,mellevo=1;
00531 int err=Lis->MoverCte(Cte,'p');
00532 while ((!err) && (mellevo)) {
00533 cif=Lis->ObtCte(Cte);
00534 if (cif==(MAXBASE-1)) {
00535 Lis->ModifCte(Cte,0);
00536 Lis->MoverCte(Cte,'s');}
00537 else {
00538 Lis->ModifCte(Cte,cif+1);
00539 mellevo=0;}
00540 }
00541 if (mellevo)
00542 Lis->InsDespues(Cte,1);}
00543 return(*this);
00544 }
00545
00546 BigNum& BigNum::operator--()
00547 {
00548
00549 PNDoble Cte;
00550 if (signo==-1) {
00551 BigNum a;
00552 signo=1;
00553 (*this)++;
00554 signo=-1;}
00555 else
00556 {
00557 TDato cif,mellevo=1;
00558 int err=Lis->MoverCte(Cte,'p');
00559 while ((!err) && (mellevo)) {
00560 cif=Lis->ObtCte(Cte);
00561 if (!cif) {
00562 Lis->ModifCte(Cte,MAXBASE-1);
00563 Lis->MoverCte(Cte,'s');}
00564 else {
00565 Lis->ModifCte(Cte,cif-1);
00566 mellevo=0;}
00567 }
00568 if (Lis->Vacia())
00569 signo=-1;
00570 if (mellevo)
00571 Lis->InsDespues(Cte,1);
00572 if ((Lis->CantElem()==1) && (Lis->ObtCte(Cte)==0))
00573 Lis->Vaciar();
00574 else {
00575 Lis->MoverCte(Cte,'u');
00576 if (Lis->ObtCte(Cte)==0)
00577 Lis->ElimCte(Cte);
00578 }
00579 }
00580 return(*this);
00581 }
00582
00583 BigNum& BigNum::operator +=(const BigNum & a)
00584 {
00585
00586
00587 if (a.signo!=signo) {
00588 if (a.signo==-1) {
00589 const_cast<BigNum&>(a).signo=1;
00590 (*this)-=a;
00591 const_cast<BigNum&>(a).signo=-1;}
00592 else {
00593 signo=1;
00594 (*this)-=a;
00595 signo*=-1;}
00596 return(*this);}
00597 TDato mellevo=0;
00598 TMayor aux;
00599 PNDoble Cte, CteA;
00600 int err=Lis->MoverCte(Cte,'p'),err_a=a.Lis->MoverCte(CteA,'p');
00601 while ((!err) && (!err_a)) {
00602 aux=Lis->ObtCte(Cte)+a.Lis->ObtCte(CteA)+mellevo;
00603 Lis->ModifCte(Cte,aux % MAXBASE);
00604 mellevo=aux / MAXBASE;
00605 err=Lis->MoverCte(Cte,'s');
00606 err_a=a.Lis->MoverCte(CteA,'s');}
00607 if (!err_a)
00608 if (mellevo)
00609 if (!err) {
00610 Lis->MoverCte(Cte,'u');
00611 Lis->InsDespues(Cte,mellevo);}
00612 else {
00613 do {
00614 aux=Lis->ObtCte(Cte)+mellevo;
00615 Lis->ModifCte(Cte,aux % MAXBASE);
00616 mellevo=aux / MAXBASE;
00617 err=Lis->MoverCte(Cte,'s');}
00618 while ((!err) && (mellevo));}
00619 else
00620 if (mellevo) {
00621 do {
00622 aux=a.Lis->ObtCte(CteA)+mellevo;
00623 Lis->InsDespues(Cte,aux % MAXBASE);
00624 mellevo=aux / MAXBASE;
00625 err_a=a.Lis->MoverCte(CteA,'s');}
00626 while ((!err_a) && (mellevo));}
00627 while (!err_a) {
00628 Lis->InsDespues(Cte,a.Lis->ObtCte(CteA));
00629 err_a=a.Lis->MoverCte(CteA,'s');}
00630 if (mellevo)
00631 Lis->InsDespues(Cte,mellevo);
00632 return(*this);
00633 }
00634 BigNum& BigNum::operator-=(const BigNum & a)
00635 {
00636 if (&a==this) {
00637 Lis->Vaciar();
00638 signo=1;
00639 return(*this);}
00640 if (a.signo==-1) {
00641 const_cast<BigNum&>(a).signo=1;
00642 (*this)+=a;
00643 const_cast<BigNum&>(a).signo=-1;
00644 return(*this);}
00645 else
00646 if (signo==-1) {
00647 signo=1;
00648 (*this)+=a;
00649 signo=-1;
00650 return(*this);}
00651 PNDoble Cte, CteA;
00652 if (a>(*this))
00653 (*this)=(*this)-a;
00654 else {
00655 TDato mellevo=0;
00656 signed long int aux;
00657 int err=Lis->MoverCte(Cte,'p'),err_a=a.Lis->MoverCte(CteA,'p');
00658 while (!err_a) {
00659 aux=Lis->ObtCte(Cte)-a.Lis->ObtCte(CteA)-mellevo;
00660 if (aux<0) {
00661 Lis->ModifCte(Cte,aux+MAXBASE);
00662 mellevo=1;}
00663 else {
00664 Lis->ModifCte(Cte,aux);
00665 mellevo=0;}
00666 Lis->MoverCte(Cte,'s');
00667 err_a=a.Lis->MoverCte(CteA,'s');}
00668 while (mellevo) {
00669 aux=Lis->ObtCte(Cte)-mellevo;
00670 if (aux<0) {
00671 Lis->ModifCte(Cte,aux+MAXBASE);
00672 mellevo=1;}
00673 else {
00674 Lis->ModifCte(Cte,aux);
00675 mellevo=0;}
00676 Lis->MoverCte(Cte,'s');}
00677 for (err=Lis->MoverCte(Cte,'u');((!err) && (Lis->ObtCte(Cte)==0));err=Lis->MoverCte(Cte,'u'))
00678 Lis->ElimCte(Cte);
00679 }
00680 return(*this);
00681 }
00682
00683 BigNum& BigNum::operator *=(const BigNum & a)
00684 {
00685 *this=a*(*this);
00686 return(*this);
00687 }
00688
00689 BigNum& BigNum::operator /=(const BigNum & a)
00690 {
00691 *this=(*this)/a;
00692 return(*this);
00693 }
00694
00695 BigNum& BigNum::operator %=(const BigNum & a)
00696 {
00697 *this=(*this)%a;
00698 return(*this);
00699 }