Closed AnttiParaoanu closed 3 years ago
@gretingz Thanks for reporting, will take a look. It's the Decimal::round()
and its truncated flag basically which in cases like this shouldn't be taken into account.
This issue seems to affect that C++ code as well (verified).
In this particular case, I think it can be solved like this: tracking number of significant digits (along the total number of digits) when parsing a decimal. Then, in this case, truncated
flag won't be set it all.
Is there anything else though?
@aldanor My expectation is that you are correct. I just wanted to point out that it is likely your inherited this bug from me. Tracing bugs is important!
The fix is trivial as you have no doubt realized. Here is what I added in C++:
if(answer.num_digits > 0) {
// We potentially need the answer.num_digits > 0 guard because we
// prune leading zeros. So with answer.num_digits > 0, we know that
// we have at least one non-zero digit.
const char *preverse = p - 1;
int32_t trailing_zeros = 0;
while ((*preverse == '0') || (*preverse == '.')) {
if(*preverse == '0') { trailing_zeros++; };
--preverse;
}
answer.decimal_point += int32_t(answer.num_digits);
answer.num_digits -= uint32_t(trailing_zeros);
}
This is not the prettiest code, but basically, I run in reverse, counting the number of trailing zeroes and I subtract it from the number of digits, which corrects the truncated check later.
@aldanor To reproduce it with 64-bit floats, use 9007199254740993.0 and then append many zeros to trigger the truncated flag.
For some floats with a long trail of zeroes, the value is not correctly rounded after a sufficient amount of zeroes.
Code:
Output:
Works in debug and release modes
rustc --version --verbose