mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-19 05:40:38 +01:00
[poincare/decimal] Fix rounding error when buidling 0.9999...
This commit is contained in:
committed by
Léa Saviot
parent
b5bf3b0bbc
commit
6d4404d4b7
@@ -287,6 +287,13 @@ Decimal Decimal::Builder(const char * integralPart, int integralPartLength, cons
|
||||
}
|
||||
//TODO: set a FLAG to tell that a rounding happened?
|
||||
bool rounding = integralPartLength > PrintFloat::k_numberOfStoredSignificantDigits && integralPart[PrintFloat::k_numberOfStoredSignificantDigits] >= '5';
|
||||
/* At this point, the exponent has already been computed. In the very special
|
||||
* case where all the significant digits of the mantissa are 9, rounding up
|
||||
* must increment the exponent. For instance, rounding up 0.99...9 (whose
|
||||
* exponent is -1) yields 1 (whose exponent is 0). To that end, the
|
||||
* significant digits will be scanned successively to determine whether the
|
||||
* exponent should be incremented. */
|
||||
bool incrementExponentAfterRoundingUp = true;
|
||||
// Cap the length of the integralPart
|
||||
integralPartLength = integralPartLength > PrintFloat::k_numberOfStoredSignificantDigits ? PrintFloat::k_numberOfStoredSignificantDigits : integralPartLength;
|
||||
Integer numerator(integralPart, integralPartLength, false);
|
||||
@@ -301,13 +308,22 @@ Decimal Decimal::Builder(const char * integralPart, int integralPartLength, cons
|
||||
}
|
||||
rounding |= integralPartLength+fractionalPartLength > PrintFloat::k_numberOfStoredSignificantDigits && fractionalPart[PrintFloat::k_numberOfStoredSignificantDigits-integralPartLength] >= '5';
|
||||
fractionalPartLength = integralPartLength+fractionalPartLength > PrintFloat::k_numberOfStoredSignificantDigits ? PrintFloat::k_numberOfStoredSignificantDigits - integralPartLength : fractionalPartLength;
|
||||
while (incrementExponentAfterRoundingUp && integralPartLength-- > 0) {
|
||||
incrementExponentAfterRoundingUp = (*(integralPart++) == '9');
|
||||
}
|
||||
for (int i = 0; i < fractionalPartLength; i++) {
|
||||
numerator = Integer::Multiplication(numerator, base);
|
||||
assert(*fractionalPart >= '0' && *fractionalPart <= '9');
|
||||
numerator = Integer::Addition(numerator, Integer(*fractionalPart-'0'));
|
||||
incrementExponentAfterRoundingUp &= (*fractionalPart == '9');
|
||||
fractionalPart++;
|
||||
}
|
||||
numerator = rounding ? Integer::Addition(numerator, Integer(1)) : numerator;
|
||||
if (rounding) {
|
||||
numerator = Integer::Addition(numerator, Integer(1));
|
||||
if (incrementExponentAfterRoundingUp) {
|
||||
exponent++;
|
||||
}
|
||||
}
|
||||
exponent = numerator.isZero() ? 0 : exponent;
|
||||
return Decimal::Builder(numerator, exponent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user