C语言程序设计,谭浩强老师第三版里面的一个关于浮点型数据的舍入误差问题

程序是这个样子的:
#include<stdio.h>
void main()
{
float a,b;
a=0;
a=123456.789e5;
b=a+20;
printf("%f,%f\n",a,b);
}
书本上说:a和b的输出结果是一样的,但是我在VC++里面运行的结果却是:
12345678848.000000,12345678868.000000
明显是不一样的……此外,我将a的赋值语句改为了"a=123456.78"然后输出a,但是输出的结果却是123456.781250,求解释!

1.-->>问:将a的赋值语句改为了"a=123456.78"然后输出a,但是输出的结果却是123456.781250....
 -->>答;计算机以二进制存储数据,因此它的权只能是:……,8,4,2,1,0.5,0.25,0.125,……。再看0.78=1*0.5 +1*0.25 +0*0.125 +0*0.0625 +1*0.03125,即可以看到是0.781250 <<---

2.->>问:我在VC++里面运行的结果却是:12345678848.000000,12345678868.000000明显是不一样的……
 -->>答:VC6.0里确实是这样。
    浮点型在VC6.0中占4个字节(32BIT),以1BIT数符,23BIT小数部分,8BIT指数的形式存储(书中有讲)。小数部分最小为0000……0001(最后一位为1),等于十进制的0.00000011920928955078125(23位小数)。当相加或相减的两个数,数量级相差20左右时,由于精度问题便出现书本所说的情况。数量相差级大于23,就肯定是白加了。(个人观点仅供参考)
温馨提示:答案为网友推荐,仅供参考
第1个回答  2012-02-21
很正常,在计算机里面,如果输入的是浮点数,也就是我们说的实数,小数点数,在存入到计算机的时候,是不能够完全一模一样存入的,这涉及到小数点后面的数进行扩展的问题,也就是用二进制位来存小数点后面的数的时候是要转换的,这样,如果再次输出这个转换的数的话,还要进行一次转换,这转来转去就夹杂了数的精度的问题。当然,你看到的就不是以前的数啦。但是是它的一个精度扩大的数。
你要想看到你原来的数,可以控制一下输出小数点的位数,你把这个输出格式换一下printf("%f,%f\n",a,b);-------》printf("%e,%e\n",a,b);
或者你用f格式的时候变成printf("%.2f,%.2f\n",a,b);追问

嗯。那么,根据书本上说的:因为a的数值比较大,而20比较小,当这两个数相加的时候,20会被忽略不计,从而a和b输出的结果是一样的,但是我运行的程序后,他们输出的结果不同,a是12345678900.00,而b是12345678920.00,是书本错了?

追答

怎么是忽略不计呢?
是先把20转换成浮点型 然后在进行相加
其实,你可以理解就是两个数相加的话,要对其格式,那一个有小数点,一个没有,怎么对齐,要是让你在纸上做,那就人为对齐了,计算机呢。那就按一个格式来,整数可以转换成扩大的实数,数值的大小并不变,而要是实数裁剪成整数,那岂不是把数的一部分没啦,所以只好按照扩大来转换,再进行相加。
我不知道你书上怎么说忽略不计,这是在什么情况下说的。你看一下。我不知道。

本回答被提问者采纳
第2个回答  2012-02-23
我在VS上刚刚调试了,结果都是12345678848.000000
不知道你是怎么调试的?