- /*
- 题目:
- printf("%.20lf\n",1.23456+56789.0007);的输出结果是多少,
- 这个结果和笔算的结果一致吗?
- 如果希望得到和笔算完全一致的结果,你会怎样设计程序。
- */
- #include <stdio.h>
- #include <stdlib.h>
- int main( void )
- {
-
- printf("%.20lf\n",1.23456+56789.0007);
-
- system("PAUSE");
- return 0;
- }
就一般情况而言,很难说
- printf("%.20lf\n",1.23456+56789.0007);
的输出结果究竟是什么。因为C语言并没有具体规定double类型的尺寸和表示形式。但在多数计算机上,浮点数采用IEEE 754国际标准。
在我的机器上
- printf("%.20lf\n",1.23456+56789.0007);
的输出结果是:
56790.23525999999400000000
从这个结果不难发现,尽管输出包含了小数点后面20位 这个结果和笔算结果是不一致的。这个输出结果只是笔算结果的一个近似结果。
这就是浮点类型数据的一个根本性质——在一般意义上,浮点类型数据只是对有理数的近似表示。代码中的double类型常量1.23456被编译后的二进制表示并不一定就精确等于1.23456而只是1.23456的一个近似值,56789.0007也是如此。这样表达式1.23456+56789.0007求出的同样也是一个近似值就不奇怪了。
我们平时的笔算和计算机中的浮点运算是不同的。多数情况下平时的笔算是一种精确的计算,它的基础是整数运算,是由几个部分的整数运算的组合。所以如果希望得到和笔算完全一致的结果,应该用整数运算模拟这个过程。
首先用两个整数分别存储整数部分和小数部分
- int zsbf1 = 1 , xsbf1 = 23456 ; //整数部分,小数部分
- int zsbf2 = 56789 , xsbf2 = 70 ;
- int he_zsbf , he_xsbf ; //存储和
然后整数部分和小数部分分别相加
- he_zsbf = zsbf1 + zsbf2 ;
- he_xsbf = xsbf1 + xsbf2 ;
还要考虑到可能存在的进位
- he_zsbf += he_xsbf / 100000 ;
- he_zsbf %= 100000 ;
最后分别输出整数部分和小数部分。
- #include <stdio.h>
- #include <stdlib.h>
- int main( void )
- {
- int zsbf1 = 1 , xsbf1 = 23456 ; //整数部分,小数部分
- int zsbf2 = 56789 , xsbf2 = 70 ;
- int he_zsbf , he_xsbf ; //存储和
-
- he_zsbf = zsbf1 + zsbf2 ;
- he_xsbf = xsbf1 + xsbf2 ;
- he_zsbf += he_xsbf / 100000 ;
- he_xsbf %= 100000 ;
-
- printf("1.23456+56789.0007="
- "%d.%d\n" , he_zsbf , he_xsbf );
-
- system("PAUSE");
- return 0;
- }
运行结果为:
1.23456+56789.0007=56790.23526
请按任意键继续. . .
这个题目的写法并不具备多少一般意义,其中甚至有些非常丑陋的内容,如“10000”这个字面常量以及明显有着人工雕琢过成分的“70”。这个题目的目的在于希望读者理解浮点类型以及浮点运算:浮点类型数据的值并不一定就是在代码中写出的那个浮点常量,浮点运算也并不等同于平时小数运算的那种笔算。浮点类型的本质是:近似地表示以及近似地运算,这一点和整数类型截然不同。
阅读(3331) | 评论(0) | 转发(0) |