打印实数
在不借助库函数的情况下,如何输出一个实数?
初步想法是分成三步:
- 打印整数部分;
- 打印小数点;
- 打印小数部分。
若将小数部分转化为整数来输出,那么实际上就只有两个步骤,实现打印整数是核心。作为一个练习,这儿将打印一个整数以递归的方式来实现,见下面的pring_int
函数。由于double
类型存储小数时精确度有限,这儿取15位数字,即整数位数加上小数部分的位数为15,经过试验,取15位最贴近实际的数值,与用printf
打印的实数基本无差别。需要指出的是,下面实现的print_fract
用于打印小数部分,没有考虑效率问题,仅仅是不停的对f
乘以10,只要f
还大于0,那么其小数数位就还存在,每次打印乘以10后多出来的整数部分。
下面的算法还简单的考虑了是否需要打印小数点的情况,即如果输入就是整数,那么没必要打印小数点和小数部分了。
1 /*
2 * print_real_numbers.c - Print a real number without the help of library.
3 *
4 * BUG: can't handle negative numbers or very large numbers.
5 *
6 * History:
7 *
8 * Created on 2015-4-10 by YU Heng-yang.
9 */
10 #include <stdio.h>
11 #include <assert.h>
12
13 typedef long long ll;
14
15 #define PRECISION 15
16
17 int nint = 0;
18
19 void print_digit(int d)
20 {
21 assert(d >= 0 && d < 10);
22 putchar(d + '0');
23 }
24
25 void print_int(ll n)
26 {
27 nint++;
28 if (n < 10)
29 print_digit(n);
30 else {
31 print_int(n/10);
32 print_digit(n%10);
33 }
34 }
35
36 void print_fract(double f)
37 {
38 int count = PRECISION - nint;
39
40 if (count > 0) {
41 if (f > 0.0f)
42 putchar('.');
43
44 while (count-- > 0 && f > 0.0f) {
45 f *= 10;
46 print_int((ll)f);
47 f -= (ll)f;
48 }
49 }
50 }
51
52 void print(double d)
53 {
54 print_int((ll)d);
55 print_fract(d - (ll)d);
56 }
57
58 int main()
59 {
60 double d;
61
62 while (EOF != scanf("%lf", &d)) {
63 nint = 0;
64 print(d);
65 printf(" %.30lf", d);
66 putchar('\n');
67 }
68
69 return 0;
70 }