cg_x64_fp_format_fixed_digits.c (1565B)
1 typedef unsigned long size_t; 2 3 typedef struct { 4 char* buf; 5 size_t cap; 6 size_t len; 7 } Out; 8 9 static void out_ch(Out* out, char ch) { 10 if (out->cap && out->len + 1U < out->cap) out->buf[out->len] = ch; 11 out->len++; 12 } 13 14 static double pow10_u(unsigned n) { 15 double value = 1.0; 16 while (n-- > 0) value *= 10.0; 17 return value; 18 } 19 20 static void format_fixed_abs(Out* out, double value, unsigned prec) { 21 double rounded; 22 double pow10 = 1.0; 23 int emitted = 0; 24 25 rounded = value + 0.5 / pow10_u(prec); 26 if (rounded >= 1.0) { 27 for (;;) { 28 double next = pow10 * 10.0; 29 if (!(next > pow10) || next > rounded) break; 30 pow10 = next; 31 } 32 } 33 34 while (pow10 >= 1.0) { 35 int digit = (int)(rounded / pow10); 36 if (digit < 0) digit = 0; 37 if (digit > 9) digit = 9; 38 out_ch(out, (char)('0' + digit)); 39 rounded -= (double)digit * pow10; 40 pow10 /= 10.0; 41 emitted = 1; 42 } 43 if (!emitted) out_ch(out, '0'); 44 45 out_ch(out, '.'); 46 for (unsigned i = 0; i < prec; i++) { 47 int digit; 48 rounded *= 10.0; 49 digit = (int)rounded; 50 if (digit < 0) digit = 0; 51 if (digit > 9) digit = 9; 52 out_ch(out, (char)('0' + digit)); 53 rounded -= (double)digit; 54 } 55 } 56 57 int test_main(void) { 58 char buf[16]; 59 Out out; 60 out.buf = buf; 61 out.cap = sizeof(buf); 62 out.len = 0; 63 format_fixed_abs(&out, 12.375, 2); 64 buf[out.len] = '\0'; 65 if (buf[0] != '1') return 20; 66 if (buf[1] != '2') return 21; 67 if (buf[2] != '.') return 22; 68 if (buf[3] != '3') return 23; 69 if (buf[4] != '8') return 24; 70 if (out.len != 5) return 25; 71 return 42; 72 }