提交 9743a399 编写于 作者: R Rich Felker

fix incorrect rounding in printf floating point corner cases

the printf floating point formatting code contains an optimization to
avoid computing digits that will be thrown away by rounding at the
specified (or default) precision. while it was correctly retaining all
places up to the last decimal place to be printed, it was not
retaining enough precision to see the next nonzero decimal place in
all cases. this could cause incorrect rounding down in round-to-even
(default) rounding mode, for example, when printing 0.5+DBL_EPSILON
with "%.0f".

in the fix, LDBL_MANT_DIG/3 is a lazy (non-sharp) upper bound on the
number of zeros between any two nonzero decimal digits.
上级 ba231cf9
...@@ -314,7 +314,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) ...@@ -314,7 +314,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
} }
while (e2<0) { while (e2<0) {
uint32_t carry=0, *b; uint32_t carry=0, *b;
int sh=MIN(9,-e2); int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3+8)/9;
for (d=a; d<z; d++) { for (d=a; d<z; d++) {
uint32_t rm = *d & (1<<sh)-1; uint32_t rm = *d & (1<<sh)-1;
*d = (*d>>sh) + carry; *d = (*d>>sh) + carry;
...@@ -324,7 +324,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) ...@@ -324,7 +324,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
if (carry) *z++ = carry; if (carry) *z++ = carry;
/* Avoid (slow!) computation past requested precision */ /* Avoid (slow!) computation past requested precision */
b = (t|32)=='f' ? r : a; b = (t|32)=='f' ? r : a;
if (z-b > 2+p/9) z = b+2+p/9; if (z-b > need) z = b+need;
e2+=sh; e2+=sh;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册