这事儿要从一周前讲起,有人在群里问了这么一道题,要求用 C 实现:
习题 2-5 分数化小数(decimal)
输入正整数 a,b,c,输出 a/b 的小数形式,精确到小数点后 c 位。a,b<=10^6,c<=100。输入包含多组数据,结束标记为 a=b=c=0。
样例输入:
1 6 4
0 0 0
样例输出:
0.1667
当时我做了个简化的版本 —— 最多处理 1000 组输入,并且 c 比较小(即不需要高精度)的情况的代码,主要是做一个字符串处理,来构造一个传给 printf()
的格式控制字符串,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <stdio.h> #include <stdlib.h> #include <string.h>
int main() { unsigned int a[1000], b[1000], c[1000], cnt = 0; double ans[1000]; for (int i = 0;; i++) { if (cnt == 1000) { break; } scanf("%u%u%u", &a[i], &b[i], &c[i]); cnt++; if (!(a[i] == 0 && b[i] == 0 && c[i] == 0)) { if (b[i] != 0) { ans[i] = a[i] * 1.0 / b[i]; } } else { break; } } for (int i = 0; i < cnt - 1; i++) { char formatMsgP1[] = "%."; char *formatMsgP2; if (c[i] > 99) { formatMsgP2 = malloc(sizeof(char) * 3); } else if (c[i] > 9) { formatMsgP2 = malloc(sizeof(char) * 2); } else { formatMsgP2 = malloc(sizeof(char)); } itoa(c[i], formatMsgP2, 10); char formatMsgP3[] = "lf\n"; char formatMsg[20]; strcat(formatMsg, formatMsgP1); strcat(formatMsg, formatMsgP2); strcat(formatMsg, formatMsgP3); printf(formatMsg, ans[i]); memset(formatMsg, 0, sizeof(formatMsg)); free(formatMsgP2); } return 0; }
|
这样的代码就比较麻烦,大量的代码都用在字符串拼接了。但今天看到一篇文章(《使用变量设定小数点位数》),才知道原来根本不需要那么麻烦。
本来我的目标是构造这么一个格式控制字符串 %.<c>lf
,其中 <c>
需要由用户输入。上边的思路就是输入数字之后用 itoa()
函数把输入的数字转成字符串,然后拼一拼。
但实际上可以这样:
1
| printf("%.*lf", c[i], ans[i]);
|
使用 *
,printf()
就知道了,需要去后边找这么一个参数。
所以上边 return 0;
前面那个 for
里那么多东西都只要换成这一句就行了。
下边贴出一个用动态数组实现的任意组数数据输入的代码(依然没有高精度,我不会啊):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <stdio.h> #include <stdlib.h> #include <string.h>
struct NUMS { unsigned int c; double ans; };
struct NUMS *p = 0; unsigned long long size = 0;
void append(unsigned int, double);
int main() { int a = 0, b = 0, c = 0;
do { scanf("%u%u%u", &a, &b, &c); if (a == 0 && b == 0 && c == 0) break; else { double tmp_ans = a * 1.0 / b; append(c, tmp_ans); } } while (1); for (int i = 0; i < size; i++) { printf("%.*lf\n", (p + i)->c, (p + i)->ans); } return 0; }
void append(unsigned int _c, double _ans) { if (p == 0) { p = calloc(1, sizeof(struct NUMS)); p->c = _c; p->ans = _ans; size++; } else { struct NUMS *tmp = calloc(size, sizeof(struct NUMS)); memcpy(tmp, p, sizeof(struct NUMS) * size); free(p); p = calloc(size + 1, sizeof(struct NUMS)); memcpy(p, tmp, sizeof(struct NUMS) * (size + 1)); (p + size)->c = _c; (p + size)->ans = _ans; size++; free(tmp); } }
|