示例#1
0
void qore_number_private::getAsString(QoreString& str, bool round) const {
   // first check for zero
   if (zero()) {
      str.concat("0");
      return;
   }

   mpfr_exp_t exp;

   char* buf = mpfr_get_str(0, &exp, 10, 0, num, QORE_MPFR_RND);
   if (!buf) {
      numError(str);
      return;
   }
   ON_BLOCK_EXIT(mpfr_free_str, buf);

   //printd(5, "qore_number_private::getAsString(round: %d) this: %p buf: '%s'\n", round, this, buf);

   // if it's a regular number, then format accordingly
   if (number()) {
      int sgn = sign();
      qore_size_t len = str.size() + (sgn < 0 ? 1 : 0);
      //printd(5, "qore_number_private::getAsString() this: %p '%s' exp "QLLD" len: "QLLD"\n", this, buf, exp, len);

      qore_size_t dp = 0;

      str.concat(buf);
      // trim the trailing zeros off the end
      str.trim_trailing('0');
      if (exp <= 0) {
	 exp = -exp;
	 str.insert("0.", len);
	 dp = len + 1;
	 //printd(5, "qore_number_private::getAsString() this: %p str: '%s' exp: "QLLD" dp: "QLLD" len: "QLLD"\n", this, str.getBuffer(), exp, dp, len);
	 if (exp)
	    str.insertch('0', len + 2, exp);
      }
      else {
	 // get remaining length of string (how many characters were added)
	 qore_size_t rlen = str.size() - len;

	 //printd(5, "qore_number_private::getAsString() this: %p str: '%s' exp: "QLLD" rlen: "QLLD"\n", this, str.getBuffer(), exp, rlen);

	 // assert that we have added at least 1 character
	 assert(rlen > 0);
	 if ((qore_size_t)exp > rlen)
	    str.insertch('0', str.size(), exp - rlen);
	 else if ((qore_size_t)exp < rlen) {
	    str.insertch('.', len + exp, 1);
	    dp = len + exp;
	 }
      }
      // try to do some rounding (noise reduction with binary->decimal conversions)
      if (dp && round)
         applyRoundingHeuristic(str, dp, str.size());
   }
   else
      str.concat(buf);

   //printd(5, "qore_number_private::getAsString() this: %p returning '%s'\n", this, str.getBuffer());
}
示例#2
0
int qore_number_private::formatNumberString(QoreString& num, const QoreString& fmt, ExceptionSink* xsink) {
   assert(!num.empty());
   assert(num.getEncoding() == fmt.getEncoding());
   // get the length of the format string in characters (not bytes)
   qore_size_t fl = fmt.length();
   if (fmt.empty() || fl == 2) {
      printd(5, "qore_number_private::formatNumberString() invalid format string: '%s' for number: '%s'\n", fmt.getBuffer(), num.getBuffer());
      return 0;
   }

   // get thousands separator character
   QoreString tsep;
   if (tsep.concat(fmt, 0, 1, xsink))
      return -1;

   // decimal separator
   QoreString dsep;
   // number of digits after the decimal separator
   unsigned prec = 0;
   if (fl > 1) {
      if (dsep.concat(fmt, 1, 1, xsink))
         return -1;
      // get byte offset of start of decimal precision number
      qore_offset_t i = fmt.getByteOffset(2, xsink);
      if (*xsink)
         return -1;
      assert(i >= 2);
      prec = atoi(fmt.getBuffer() + i);
      if (!prec)
         dsep.clear();
   }

   //printd(5, "qore_number_private::formatNumberString() tsep: '%s' dsep: '%s' prec: %d '%s'\n", tsep.getBuffer(), dsep.getBuffer(), prec, num.getBuffer());

   // find decimal point
   qore_offset_t dp = num.find('.');
   if (dp != -1) {
      // how many digits do we have now after the decimal point
      qore_size_t d = num.strlen() - dp - 1;
      assert(d);
      if (d < prec)
         num.addch('0', prec - d);
      else if (d > prec) {
         if ((num[dp + prec + 1] > '4') && (roundUp(num, dp + prec)))
            ++dp;
         num.terminate(dp + prec + 1);
      }
      // now substitute decimal point if necessary
      if (dsep.strlen() != 1 || dsep[0] != '.')
         num.replace(dp, 1, dsep.getBuffer());
   }
   else {
      dp = num.size();
      if (prec) {
         // add decimal point
         num.concat(&dsep, xsink);
         assert(!*xsink);
         // add zeros for significant digits
         num.addch('0', prec);
      }
   }

   // now insert thousands separator
   // start of digits before the decimal point
   qore_offset_t ds = num[0] == '-' ? 1 : 0;

   // work backwards from the decimal point
   qore_offset_t i = dp - 3;
   while (i > ds) {
      num.replace(i, 0, tsep.getBuffer());
      i -= 3;
   }

   //printd(0, "qore_number_private::formatNumberString() ok '%s'\n", num.getBuffer());

   //assert(false); xxx
   return 0;
}