comparison sprintf/float.c @ 46:38cf7fa65976

sprintf/float.c: rounding corner case bug
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 29 Sep 2017 03:23:01 +0000
parents a2d5d622e19e
children
comparison
equal deleted inserted replaced
45:a2d5d622e19e 46:38cf7fa65976
41 if (*end == '.') 41 if (*end == '.')
42 --end; 42 --end;
43 if (++*end <= '9') 43 if (++*end <= '9')
44 break; 44 break;
45 *end = '0'; 45 *end = '0';
46 if (end == start) {
47 *--end = '1';
48 return(1);
49 }
46 } 50 }
47 /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ 51 /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
48 else if (sign == '-') 52 else if (sign == '-')
49 for (;; --end) { 53 for (;; --end) {
50 if (*end == '.') 54 if (*end == '.')
51 --end; 55 --end;
52 if (*end != '0') 56 if (*end != '0')
53 break; 57 break;
54 if (end == start) 58 if (end == start)
55 return(1); /* clear the -ve */ 59 return(-1); /* clear the -ve */
56 } 60 }
57 return(0); 61 return(0);
58 } 62 }
59 63
60 u_char * 64 u_char *
62 double number, int prec) 66 double number, int prec)
63 { 67 {
64 char buf[MAX_INT_DIGITS + 1 + MAXFRACT]; 68 char buf[MAX_INT_DIGITS + 1 + MAXFRACT];
65 int extra_prec = 0; 69 int extra_prec = 0;
66 int origsign = sign; 70 int origsign = sign;
71 int round_stat;
67 double fract, tmp; 72 double fract, tmp;
68 char *start, *t; 73 char *start, *t;
69 74
70 /* first order of business: weed out infinities and NaNs */ 75 /* first order of business: weed out infinities and NaNs */
71 if (isinf(number)) { 76 if (isinf(number)) {
102 if (prec) 107 if (prec)
103 do { 108 do {
104 fract = modf(fract * 10, &tmp); 109 fract = modf(fract * 10, &tmp);
105 *t++ = tochar((int)tmp); 110 *t++ = tochar((int)tmp);
106 } while (--prec && fract); 111 } while (--prec && fract);
107 if (fract && f_round(fract, start, t - 1, sign)) 112 if (fract) {
108 sign = origsign; 113 round_stat = f_round(fract, start, t - 1, sign);
114 if (round_stat == 1)
115 start--;
116 else if (round_stat == -1)
117 sign = origsign;
118 }
109 } 119 }
110 return _sprintf_field(op, width, flags, sign, start, t - start, 120 return _sprintf_field(op, width, flags, sign, start, t - start,
111 0, prec + extra_prec); 121 0, prec + extra_prec);
112 } 122 }