Logo Search packages:      
Sourcecode: yacas version File versions  Download package

void BigNumber::ToString ( LispString aResult,
LispInt  aPrecision,
LispInt  aBase = 10 
) const

ToString : return string representation of number in aResult to given precision (base digits).

Export a number to a string in given base to given base digits.

ToString : return string representation of the number at given precision (base digits) in aResult.

Definition at line 1833 of file gmpnumbers.cpp.

References Double(), LispString::SetStringCounted(), SetTo(), and Sign().

{
  if (aBase<2 || aBase>32)
  {
      RaiseError("BigNumber::ToString: error: aBase should be between 2 and 32, not %d\n", aBase);
      return;
  }
  if (IsInt())
  {   // find how many chars we need
      LispInt size=mpz_sizeinbase(int_, aBase);
      char* buffer=(char*)malloc(size+2);
      mpz_get_str(buffer, aBase, int_);
      // assign result
      aResult.SetStringCounted(buffer, strlen(buffer));
      free(buffer);
  }
  else
  {   // we have a floating-point number.
      // note: aPrecision means *base digits* here
      LISPASSERT(aPrecision>=0);
      if (aPrecision <=0)
            aPrecision = 1;   // refuse to print with 0 or fewer digits
    unsigned long size=(unsigned long)aPrecision;
    // how many base digits to print
    unsigned long print_prec = bits_to_digits((unsigned long)iPrecision, aBase);
      print_prec = MIN(print_prec, (unsigned long)aPrecision);
    // the size needed to print the exponent cannot be more than 200 chars since we refuse to print exp-floats
    size += 200;
    char* buffer=(char*)malloc(size);
    if (!buffer)
    {
          RaiseError("BigNumber::ToString: out of memory printing %e (prec. %d) to %d digits, need %ld chars", this->Double(), this->GetPrecision(), aPrecision, size);
          return;
    }
    char* offset = buffer;
    if (Sign()==0)
    {    // print zero - note that gmp does not print "0.", it prints nothing at all.
    // according to the latest revelations, the floating-point zero must be printed as "0."
          strcpy(offset, "0."); // end of string is here too
    }
    else
    {
      // print a number using fixed point if the exponent is between -4 and +8
      const long lower_exp=-4, upper_exp=8;
//    gmp_snprintf(buffer, size-1, "%*g", float_, aPrecision);
// cannot use gmp_printf because we need to print in a given base
      long exp_small;
      // get the exponent in given base and print the string at the same time
      // string is printed starting at an offset to allow for leading zeros/decimal point
      offset += 2-lower_exp;
      (void) mpf_get_str(offset, &exp_small, aBase, print_prec, float_);
      if (lower_exp <= exp_small && exp_small <= upper_exp)
      {     // print in fixed point.
            if (exp_small>0)
            {     // Insert a point somewhere in the middle. Uses memmove() if needed
                  // *offset contains something like "-123" and exp_small is 2, then we need to get "-12.3". Or perhaps we had "-123" and exp_small=5, then we need to get "-12300."
                  // point position
                  char* point_pos = offset + exp_small;
                  if (Sign()<0) ++point_pos;
                  // decide if the point is within the printed part of the string
                  size=strlen(offset);
                  if (point_pos-offset>=(signed)size) // ok here because point_pos-offset is always positive if exp_small>0
                  {     // no moving required, but perhaps need to pad with zeros, and we need to add the point
                        int i=size;
                        for(; i<point_pos-offset; ++i)
                          offset[i] = '0';
                        strcpy(offset+i, ".");  // end of string
                  }
                  else
                  {     // need to insert the point and shift the rest of the string
                        memmove(point_pos+1, point_pos, size-(point_pos-offset)+1);
                        *point_pos = '.';
                  }
            }
            else
            {// add leading zeros and decimal point, handle sign
            // we need to add (1-exp_small) zeros total
                  if (Sign()<0)
                  {     // *offset contains something like "-123..."
                        // and instead we need -0.00123... (if small_exp=-2)
                        // final offset:
                        offset = offset-(2-exp_small);
                        memcpy(offset, "-0.",3);      // 3 chars added
                        // fill more zeros
                        for (int i=3; i<3-exp_small; ++i)
                          offset[i] = '0';
                        // done printing
                  }
                  else  // the number is surely nonzero.
                  {     // *offset contains something like "123..."
                        // and instead we need 0.00123... (if small_exp=-2)
                        // final offset:
                        offset = offset-(2-exp_small);
                        memcpy(offset, "0.",2); // 2 chars added
                        // fill more zeros
                        for (int i=2; i<2-exp_small; ++i)
                          offset[i] = '0';
                        // done printing to buffer
                  }
            }     // end of printing numbers < 1
      }     // end of printing in fixed point
      else
      { // printing in floating point
            // if the number is negative, need to handle the - sign
            offset -= 2;      // final offset already known
            if (Sign()<0)
                  memcpy(offset, "-0.", 3);
            else
                  memcpy(offset, "0.", 2);
            
            // now print the exponent: either "e" or "@" and then the long integer
            size = strlen(offset);
            offset[size] = (aBase<=10) ? 'e' : '@';   // one character there, start exponent at offset size+1. Printing as per GMP instructions.
            // compute the total exponent
            BigNumber exp_total;
            exp_total.SetTo((LispInt)exp_small);
            mpz_get_str(offset+size+1, aBase, exp_total.int_);
      }
      // assign result
     }      // finished printing a float
     aResult.SetStringCounted(offset, strlen(offset));
     free(buffer);
   } // finished printing a nonzero number
}


Generated by  Doxygen 1.6.0   Back to index