/** * Currently, getDouble() depends on atof() to do its conversion. * * WARNING!! * This is an extremely costly function. ~1/2 of the conversion time * can be linked to this function. */ double DigitList::getDouble() const { // TODO: fix thread safety. Can probably be finessed some by analyzing // what public const functions can see which DigitLists. // Like precompute fDouble for DigitLists coming in from a parse // or from a Formattable::set(), but not for any others. if (fHaveDouble) { return fDouble; } DigitList *nonConstThis = const_cast<DigitList *>(this); if (isZero()) { nonConstThis->fDouble = 0.0; if (decNumberIsNegative(fDecNumber)) { nonConstThis->fDouble /= -1; } } else if (isInfinite()) { if (std::numeric_limits<double>::has_infinity) { nonConstThis->fDouble = std::numeric_limits<double>::infinity(); } else { nonConstThis->fDouble = std::numeric_limits<double>::max(); } if (!isPositive()) { nonConstThis->fDouble = -fDouble; } } else { MaybeStackArray<char, MAX_DBL_DIGITS+18> s; // Note: 14 is a magic constant from the decNumber library documentation, // the max number of extra characters beyond the number of digits // needed to represent the number in string form. Add a few more // for the additional digits we retain. // Round down to appx. double precision, if the number is longer than that. // Copy the number first, so that we don't modify the original. if (getCount() > MAX_DBL_DIGITS + 3) { DigitList numToConvert(*this); numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. numToConvert.round(MAX_DBL_DIGITS+3); uprv_decNumberToString(numToConvert.fDecNumber, s); // TODO: how many extra digits should be included for an accurate conversion? } else { uprv_decNumberToString(this->fDecNumber, s); } U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); loadDecimalChar(); if (gDecimal != '.') { char *decimalPt = strchr(s, '.'); if (decimalPt != NULL) { *decimalPt = gDecimal; } } char *end = NULL; nonConstThis->fDouble = uprv_strtod(s, &end); } nonConstThis->fHaveDouble = TRUE; return fDouble; }
/** * Currently, getDouble() depends on strtod() to do its conversion. * * WARNING!! * This is an extremely costly function. ~1/2 of the conversion time * can be linked to this function. */ double DigitList::getDouble() const { { Mutex mutex; if (fHave == kDouble) { return fUnion.fDouble; } } double tDouble = 0.0; if (isZero()) { tDouble = 0.0; if (decNumberIsNegative(fDecNumber)) { tDouble /= -1; } } else if (isInfinite()) { if (std::numeric_limits<double>::has_infinity) { tDouble = std::numeric_limits<double>::infinity(); } else { tDouble = std::numeric_limits<double>::max(); } if (!isPositive()) { tDouble = -tDouble; //this was incorrectly "-fDouble" originally. } } else { MaybeStackArray<char, MAX_DBL_DIGITS+18> s; // Note: 14 is a magic constant from the decNumber library documentation, // the max number of extra characters beyond the number of digits // needed to represent the number in string form. Add a few more // for the additional digits we retain. // Round down to appx. double precision, if the number is longer than that. // Copy the number first, so that we don't modify the original. if (getCount() > MAX_DBL_DIGITS + 3) { DigitList numToConvert(*this); numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. numToConvert.round(MAX_DBL_DIGITS+3); uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias()); // TODO: how many extra digits should be included for an accurate conversion? } else { uprv_decNumberToString(this->fDecNumber, s.getAlias()); } U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); char *end = NULL; tDouble = decimalStrToDouble(s.getAlias(), &end); } { Mutex mutex; DigitList *nonConstThis = const_cast<DigitList *>(this); nonConstThis->internalSetDouble(tDouble); } return tDouble; }
/** * Currently, getDouble() depends on strtod() to do its conversion. * * WARNING!! * This is an extremely costly function. ~1/2 of the conversion time * can be linked to this function. */ double DigitList::getDouble() const { static char gDecimal = 0; char decimalSeparator; { Mutex mutex; if (fHave == kDouble) { return fUnion.fDouble; } else if(fHave == kInt64) { return (double)fUnion.fInt64; } decimalSeparator = gDecimal; } if (decimalSeparator == 0) { // We need to know the decimal separator character that will be used with strtod(). // Depends on the C runtime global locale. // Most commonly is '.' // TODO: caching could fail if the global locale is changed on the fly. char rep[MAX_DIGITS]; sprintf(rep, "%+1.1f", 1.0); decimalSeparator = rep[2]; } double tDouble = 0.0; if (isZero()) { tDouble = 0.0; if (decNumberIsNegative(fDecNumber)) { tDouble /= -1; } } else if (isInfinite()) { if (std::numeric_limits<double>::has_infinity) { tDouble = std::numeric_limits<double>::infinity(); } else { tDouble = std::numeric_limits<double>::max(); } if (!isPositive()) { tDouble = -tDouble; //this was incorrectly "-fDouble" originally. } } else { MaybeStackArray<char, MAX_DBL_DIGITS+18> s; // Note: 14 is a magic constant from the decNumber library documentation, // the max number of extra characters beyond the number of digits // needed to represent the number in string form. Add a few more // for the additional digits we retain. // Round down to appx. double precision, if the number is longer than that. // Copy the number first, so that we don't modify the original. if (getCount() > MAX_DBL_DIGITS + 3) { DigitList numToConvert(*this); numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. numToConvert.round(MAX_DBL_DIGITS+3); uprv_decNumberToString(numToConvert.fDecNumber, s); // TODO: how many extra digits should be included for an accurate conversion? } else { uprv_decNumberToString(this->fDecNumber, s); } U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); if (decimalSeparator != '.') { char *decimalPt = strchr(s, '.'); if (decimalPt != NULL) { *decimalPt = decimalSeparator; } } char *end = NULL; tDouble = uprv_strtod(s, &end); } { Mutex mutex; DigitList *nonConstThis = const_cast<DigitList *>(this); nonConstThis->internalSetDouble(tDouble); gDecimal = decimalSeparator; } return tDouble; }