extractSignificantDigits method

String extractSignificantDigits(
  1. bool insertDecimalPoint,
  2. List<int> magnitudeList
)

Extracts the significant digits in the decimal representation of the argument. A decimal point may be optionally inserted in the string of digits (as long as its position lies within the extracted digits

  • if not, the caller must prepend or append the appropriate zeroes and decimal point).

@param y the number to extract ( >= 0) @param decimalPointPos the position in which to insert a decimal point @return the string containing the significant digits and possibly a decimal point

Implementation

String extractSignificantDigits(
    bool insertDecimalPoint, List<int> magnitudeList) {
  DD y = this.abs();
// compute *correct* magnitude of y
  int mag = magnitude(y.hi);
  DD scale = TEN.pow(mag);
  y = y.divideDD(scale);

// fix magnitude if off by one
  if (y.gt(TEN)) {
    y = y.divideDD(TEN);
    mag += 1;
  } else if (y.lt(ONE)) {
    y = y.multiplyDD(TEN);
    mag -= 1;
  }

  int decimalPointPos = mag + 1;
  StringBuffer buf = new StringBuffer();
  int numDigits = MAX_PRINT_DIGITS - 1;
  for (int i = 0; i <= numDigits; i++) {
    if (insertDecimalPoint && i == decimalPointPos) {
      buf.write('.');
    }
    int digit = y.hi.round();
//      System.out.println("printDump: [" + i + "] digit: " + digit + "  y: " + y.dump() + "  buf: " + buf);

    /**
     * This should never happen, due to heuristic checks on remainder below
     */
    if (digit < 0 || digit > 9) {
//        System.out.println("digit > 10 : " + digit);
//        throw new IllegalStateException("Internal errror: found digit = " + digit);
    }
    /**
     * If a negative remainder is encountered, simply terminate the extraction.
     * This is robust, but maybe slightly inaccurate.
     * My current hypothesis is that negative remainders only occur for very small lo components,
     * so the inaccuracy is tolerable
     */
    if (digit < 0) {
      break;
// throw new IllegalStateException("Internal errror: found digit = " + digit);
    }
    bool rebiasBy10 = false;
    String digitChar = String.fromCharCode(0);
    if (digit > 9) {
// set flag to re-bias after next 10-shift
      rebiasBy10 = true;
// output digit will end up being '9'
      digitChar = '9';
    } else {
      digitChar = '0$digit';
    }
    buf.write(digitChar);
    y = (y.subtractDD(DD.valueOf(digit.toDouble())).multiplyDD(TEN));
    if (rebiasBy10) y.selfAddDD(TEN);

    bool continueExtractingDigits = true;
    /**
     * Heuristic check: if the remaining portion of
     * y is non-positive, assume that output is complete
     */
//      if (y.hi <= 0.0)
//        if (y.hi < 0.0)
//        continueExtractingDigits = false;
    /**
     * Check if remaining digits will be 0, and if so don't output them.
     * Do this by comparing the magnitude of the remainder with the expected precision.
     */
    int remMag = magnitude(y.hi);
    if (remMag < 0 && remMag.abs() >= (numDigits - i))
      continueExtractingDigits = false;
    if (!continueExtractingDigits) break;
  }
  magnitudeList[0] = mag;
  return buf.toString();
}