Rounding-Error: Use proper banker's rounding
Isn't that comparison (first line) wrong considering the following comment?
if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++number_.integral;
}
I think it should be
if (!((remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1)) {
So, this is code from Marco Paland's original repository, which I haven't touched. It does seem a bit weird and I need to take another look.
... but I don't quite understand your suggestion, e.g. why do you suggest we avoid the equality operator.
yeah, this is inherited from the original repo, but it's still wrong compared to the embedded comment. it came up during linting of a code-base.
Doing it like that with an extra step might fix some weird float-behavior with very small remainders in the fraction-part?!
So, I just made it Banker's rounding.
In fact, I found that when executing this block, there is always remainder<=0.5, because the remainder here is updated (in line 605)
https://github.com/eyalroz/printf/blob/f8ed5a9bd9fa8384430973465e94aa14c925872d/src/printf/printf.c#L604-L611
The abs_number here is the absolute value of the original number, and the value of integral depends on whether the number is carried.
There are 3 situations at this time
- If the previous remainder>0.5 (carry), then the current
remainderis a negative number - If the previous remainder<0.5 (no carry), then the current
remainderis between the interval [0,0.5) - If the previous remainder=0.5 (special case), then the current
remainderis also 0.5, and rounding processing is executed.
So, there is never remainder>0.5, and the condition here is really a bit strange.