VisibleDigits & FixedPrecision::initVisibleDigits( double value, VisibleDigits &digits, UErrorCode &status) const { if (U_FAILURE(status)) { return digits; } digits.clear(); if (uprv_isNaN(value)) { digits.setNaN(); return digits; } if (uprv_isPositiveInfinity(value)) { digits.setInfinite(); return digits; } if (uprv_isNegativeInfinity(value)) { digits.setInfinite(); digits.setNegative(); return digits; } if (!fRoundingIncrement.isZero()) { // If we have round increment, use digit list. DigitList digitList; digitList.set(value); return initVisibleDigits(digitList, digits, status); } // Try to find n such that value * 10^n is an integer int32_t n = -1; double scaled; for (int32_t i = 0; i < UPRV_LENGTHOF(gPower10); ++i) { scaled = value * gPower10[i]; if (scaled > MAX_INT64_IN_DOUBLE || scaled < -MAX_INT64_IN_DOUBLE) { break; } if (scaled == floor(scaled)) { n = i; break; } } // Try fast path if (n >= 0 && initVisibleDigits(scaled, -n, digits, status)) { digits.fAbsDoubleValue = fabs(value); digits.fAbsDoubleValueSet = U_SUCCESS(status) && !digits.isOverMaxDigits(); // Adjust for negative 0 becuase when we cast to an int64, // negative 0 becomes positive 0. if (scaled == 0.0 && uprv_isNegative(scaled)) { digits.setNegative(); } return digits; } // Oops have to use digit list DigitList digitList; digitList.set(value); return initVisibleDigits(digitList, digits, status); }
void DigitList::set(double source, int32_t maximumDigits, UBool fixedPoint) { // for now, simple implementation; later, do proper IEEE stuff char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough) char *digitPtr = fDigits; char *repPtr = rep + 2; // +2 to skip the sign and decimal int32_t exponent = 0; fIsPositive = !uprv_isNegative(source); // Allow +0 and -0 // Generate a representation of the form /[+-][0-9]+e[+-][0-9]+/ sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source); fDecimalAt = 0; rep[2] = rep[1]; // remove decimal while (*repPtr == kZero) { repPtr++; fDecimalAt--; // account for leading zeros } while (*repPtr != 'e') { *(digitPtr++) = *(repPtr++); } fCount = MAX_DBL_DIGITS + fDecimalAt; // Parse an exponent of the form /[eE][+-][0-9]+/ UBool negExp = (*(++repPtr) == '-'); while (*(++repPtr) != 0) { exponent = 10*exponent + *repPtr - kZero; } if (negExp) { exponent = -exponent; } fDecimalAt += exponent + 1; // +1 for decimal removal // The negative of the exponent represents the number of leading // zeros between the decimal and the first non-zero digit, for // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this // is more than the maximum fraction digits, then we have an underflow // for the printed representation. if (fixedPoint && -fDecimalAt >= maximumDigits) { // If we round 0.0009 to 3 fractional digits, then we have to // create a new one digit in the least significant location. if (-fDecimalAt == maximumDigits && shouldRoundUp(0)) { fCount = 1; ++fDecimalAt; fDigits[0] = (char)'1'; } else { // Handle an underflow to zero when we round something like // 0.0009 to 2 fractional digits. fCount = 0; } return; } // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. Do NOT round in the special // case where maximumDigits == 0 and fixedPoint is FALSE. if (fixedPoint || (0 < maximumDigits && maximumDigits < fCount)) { round(fixedPoint ? (maximumDigits + fDecimalAt) : maximumDigits); } else { // Eliminate trailing zeros. while (fCount > 1 && fDigits[fCount - 1] == kZero) --fCount; } }