extractSignificantDigits method
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();
}