/** * 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; }
void DigitList::getDecimal(DecimalNumberString &str, UErrorCode &status) { if (U_FAILURE(status)) { return; } // A decimal number in string form can, worst case, be 14 characters longer // than the number of digits. So says the decNumber library doc. int32_t maxLength = fDecNumber->digits + 15; str.setLength(maxLength, status); if (U_FAILURE(status)) { return; // Memory allocation error on growing the string. } uprv_decNumberToString(this->fDecNumber, &str[0]); int32_t len = uprv_strlen(&str[0]); U_ASSERT(len <= maxLength); str.setLength(len, status); }
/** * Return a string form of this number. * Format is as defined by the decNumber library, for interchange of * decimal numbers. */ void DigitList::getDecimal(CharString &str, UErrorCode &status) { if (U_FAILURE(status)) { return; } // A decimal number in string form can, worst case, be 14 characters longer // than the number of digits. So says the decNumber library doc. int32_t maxLength = fDecNumber->digits + 14; int32_t capacity = 0; char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status); if (U_FAILURE(status)) { return; // Memory allocation error on growing the string. } U_ASSERT(capacity >= maxLength); uprv_decNumberToString(this->fDecNumber, buffer); U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength); str.append(buffer, -1, status); }
/** * 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; }