diff --git a/mfbt/decimal/Decimal.cpp b/mfbt/decimal/Decimal.cpp --- a/mfbt/decimal/Decimal.cpp +++ b/mfbt/decimal/Decimal.cpp @@ -618,26 +618,26 @@ Decimal::AlignedOperands Decimal::alignO Decimal Decimal::ceiling() const { if (isSpecial()) return *this; if (exponent() >= 0) return *this; - uint64_t result = m_data.coefficient(); - const int numberOfDigits = countDigits(result); + uint64_t coefficient = m_data.coefficient(); + const int numberOfDigits = countDigits(coefficient); const int numberOfDropDigits = -exponent(); if (numberOfDigits < numberOfDropDigits) return isPositive() ? Decimal(1) : zero(Positive); - result = scaleDown(result, numberOfDropDigits - 1); - if (sign() == Positive && result % 10 > 0) - result += 10; - result /= 10; + uint64_t result = scaleDown(coefficient, numberOfDropDigits); + uint64_t droppedDigits = coefficient - scaleUp(result, numberOfDropDigits); + if (droppedDigits && isPositive()) + result += 1; return Decimal(sign(), 0, result); } Decimal Decimal::compareTo(const Decimal& rhs) const { const Decimal result(*this - rhs); switch (result.m_data.formatClass()) { case EncodedData::ClassInfinity: @@ -660,26 +660,27 @@ Decimal Decimal::compareTo(const Decimal Decimal Decimal::floor() const { if (isSpecial()) return *this; if (exponent() >= 0) return *this; - uint64_t result = m_data.coefficient(); - const int numberOfDigits = countDigits(result); + uint64_t coefficient = m_data.coefficient(); + const int numberOfDigits = countDigits(coefficient); const int numberOfDropDigits = -exponent(); if (numberOfDigits < numberOfDropDigits) return isPositive() ? zero(Positive) : Decimal(-1); - result = scaleDown(result, numberOfDropDigits - 1); - if (isNegative() && result % 10 > 0) - result += 10; - result /= 10; + uint64_t result = scaleDown(coefficient, numberOfDropDigits); + uint64_t droppedDigits = coefficient - scaleUp(result, numberOfDropDigits); + if (droppedDigits && isNegative()) { + result += 1; + } return Decimal(sign(), 0, result); } Decimal Decimal::fromDouble(double doubleValue) { if (std::isfinite(doubleValue)) return fromString(String::numberToStringECMAScript(doubleValue)); @@ -915,16 +916,18 @@ Decimal Decimal::round() const return *this; uint64_t result = m_data.coefficient(); const int numberOfDigits = countDigits(result); const int numberOfDropDigits = -exponent(); if (numberOfDigits < numberOfDropDigits) return zero(Positive); + // We're implementing round-half-away-from-zero, so we only need the one + // (the most significant) fractional digit: result = scaleDown(result, numberOfDropDigits - 1); if (result % 10 >= 5) result += 10; result /= 10; return Decimal(sign(), 0, result); } double Decimal::toDouble() const