Avatar billede geek Nybegynder
08. maj 2003 - 20:29 Der er 14 kommentarer og
1 løsning

Gange og dividere algoritme??!

Hi eksperter...

Jeg har det problem at jeg skal kunne regne med KÆMPE store tal + MEGET små tal...
jeg har valgt at løse dette ved at skrive mine egne algoritmer for (+,-,*,/).
Er også blevet færdig med + og -
men jeg mangler en algoritme for * og /.
(de skal kunne * og / med flydende tal)

Er der en af jer der ligger inde med sådanne, eller kender et link til sådanne???

Geek
Avatar billede arne_v Ekspert
08. maj 2003 - 20:34 #1
* er ret simpel.

/ er en bitch.

Med * kan du bare bruge normal regning - det er ikke så svært.

Bruger du fixed point eller floating point ?

(jeg tror nok at jeg har noget kode liggende)
Avatar billede olennert Nybegynder
08. maj 2003 - 20:51 #2
Check også på www.boost.org. Der er et lib til kæmpe-tal (ikke til små, så vidt jeg ved, men hvor meget små tal skal du bruge? Er double for upræcis?)
Avatar billede arne_v Ekspert
08. maj 2003 - 20:56 #3
Jeg vil assume floating point.

For mange år siden skrev jeg noget kode til store floating point.

Her er koden til gange:

class BigFP operator*(const class BigFP& z1,const class BigFP& z2)
{
  if(z1.Size!=z2.Size) fp_error(EM_ONCI,"*");
  class BigFP tmp(z1.Size,0);
  // test for zero
  if(ZERO(z1)||ZERO(z2)) return tmp;
  // both nonzero
  tmp.Sign = z1.Sign ^ z2.Sign;
  tmp.Mantissa = HalfSize((DoubleSize(z1.Mantissa)*DoubleSize(z2.Mantissa))>>
                  (tmp.Mantissa.GetSize()*BITS_PR_CHAR));
  tmp.Exponent = FP_BIAS + (z1.Exponent-FP_BIAS) + (z2.Exponent-FP_BIAS) +
                  (tmp.Mantissa.GetSize()*BITS_PR_CHAR);
  tmp.Normalize();
  return tmp;
}

Logikken burde være nem at overskue.
Avatar billede arne_v Ekspert
08. maj 2003 - 20:59 #4
Division gav mig store kvaler.

Jeg endte med følgende:

class BigFP operator/(const class BigFP& z1,const class BigFP& z2)
{
  if(z1.Size!=z2.Size) fp_error(EM_ONCI,"/");
  // test for zero
  if(ZERO(z1)) return BigFP(z1.Size,0);
  if(ZERO(z2)) fp_error(EM_DBZ);
  // both nonzero
  // use iterative algorithm based on guess from highbytes of mantissa
  class BigFP leftover(z1.Size);
  class BigFP guess(z1.Size);
  class BigFP result(z1.Size,0);
  for(int i=0;i<(z1.Size/sizeof(long int)-1);i++) {
      leftover = z1 - result*z2;
      if((z1.Exponent - leftover.Exponent)>(leftover.Size-sizeof(long int))*BITS_PR_CHAR) break;
      guess = double(leftover.Mantissa.HighLong())/double(z2.Mantissa.HighLong());
      guess.Exponent = guess.Exponent + (leftover.Exponent - z2.Exponent);
      if(leftover.Sign^z2.Sign)
        result = result - guess;
      else
        result = result + guess;
  }
  return result;
}
Avatar billede arne_v Ekspert
08. maj 2003 - 21:01 #5
* bruger så BigInt * for mantissa:

class BigInt operator*(const class BigInt& z1,const class BigInt& z2)
{
  // check
  if(z1.Size!=z2.Size) int_error(EM_ONCI,"*");
  // basic algorithm: (a)(b) * (c)(d) = (ac)(0)(0) + (ad)(0) + (bc)(0) + (bd)
  class BigInt tmp(z1.Size+z2.Size,0);
  int i,j;
  long int result,carry;
  for(i=0;i<z1.Size;i++) {
      carry = 0;
      for(j=0;j<z2.Size;j++) {
        result = tmp.Data[i+j] + ULONG(z1.Data[i])*ULONG(z2.Data[j]) + carry;
        carry = result >> BITS_PR_CHAR;
        result = result - (carry << BITS_PR_CHAR);
        tmp.Data[i+j] = result;
      }
      for(j=z2.Size;j<(z1.Size+z2.Size-i);j++) {
        result = tmp.Data[i+j] + carry;
        carry = result >> BITS_PR_CHAR;
        result = result - (carry << BITS_PR_CHAR);
          tmp.Data[i+j] = result;
      }
  }
  // truncate high part
  return HalfSize(tmp);
}
Avatar billede arne_v Ekspert
08. maj 2003 - 21:02 #6
Og det er som sagt skrevet for mange år siden.

Jeg har testet noget på koden, men den har aldrig været i production.

Jeg er overbevist om at division kan laves smartere.
Avatar billede arne_v Ekspert
08. maj 2003 - 21:03 #7
Hvis du bare skal have løst problemet bedst, hurtigst og billigt - så
brug et eksisterende library.

Jeg mener mange bruger: http://www.gnu.org/software/gmp/gmp.html !

Men det er faktisk ret sjovt at arbejde med selv.

:-)
Avatar billede olennert Nybegynder
09. maj 2003 - 10:55 #8
Ups, jeg huskede forkert. Boost har ikke noget lib til store tal, men mange andre spændende ting.
Avatar billede arne_v Ekspert
09. maj 2003 - 11:07 #9
GMP burde have det nødvendige.
Avatar billede geek Nybegynder
09. maj 2003 - 18:19 #10
Hej igen...
Arne: Har ikke helt fattet alt i din kode...
Men problemet er at det skal kunne kompiles i gcc(unix), har prøvet men for self bunker af fejl :( (sikkert bare mig der er en padde)
Hvis det bare er mig kunne jeg så ikke få dig til at lave et simpelt eks med dine funktioner, som kan kompiles i gcc???

Ville gerne bruge "gnu mp" men det er ikke muligt, da jeg skal bruge det på et cluster hvor jeg ikke har adgang til at installere nyt software :(

Men hvis i kender nogle andre headerfiler eller objectfiler som kan bruges uden at skulle installeres ville det være HELT perfekt...

Geek
Avatar billede arne_v Ekspert
09. maj 2003 - 18:39 #11
Jeg prøver lige at samle noget komplet kode.
Avatar billede arne_v Ekspert
09. maj 2003 - 18:40 #12
Og den compiler med GCC !
Avatar billede arne_v Ekspert
09. maj 2003 - 22:15 #13
Klar:

http://80.199.19.48/arne/eksperten/big/big.zip

Inklusive test programmer.

[kør dem hellere og check resulatet - jeg orkede ikke !]
Avatar billede arne_v Ekspert
09. maj 2003 - 22:18 #14
Bemærk også at jeg har hevet nogle checks ud fordi de kaldte
nogle specifikke fejl-håndterings funktioner.
Avatar billede geek Nybegynder
12. maj 2003 - 18:51 #15
Se det fattede jeg en smule af!! :) hehe
Tusind tak Arne for alt hjælpen!

Geek
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester