在不借助库函数的情况下,如何输出一个实数?

初步想法是分成三步:

  • 打印整数部分;
  • 打印小数点;
  • 打印小数部分。

若将小数部分转化为整数来输出,那么实际上就只有两个步骤,实现打印整数是核心。作为一个练习,这儿将打印一个整数以递归的方式来实现,见下面的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 }