问题描述
- 初学C……求助float有效数字的问题
- 关于浮点数有效数字我有很多疑惑,我发现我读入一个浮点数后再输出,两个数字是不相等的。开始我以为是我输入的数字超过了float有效数字位数的原因,但是下面这个程序证明不是这个原因:
#include <stdio.h>#include <float.h>int main(void){float test;char data[7];printf(""Float has at least %d effective numbersn"" FLT_DIG);printf(""Then i'm gonna check it!n"");printf(""test data:_______bbbbbbb"");scanf(""%f""&test);printf(""please input again to confirm it:_______bbbbbbb"");scanf(""%s""&data);printf(""So %f is supposed to be %s"" test data);return 0;}
就是先查了一下我的机子规定float至少几个有效数字,然后输入一个数字,输两边,一次存成float,一次存成字符串,最后检验float是不是真有这么多有效数字
结果:这是怎么回事啊……我大概知道为什么会有这种情况,就是计算机把十进制转二进制存储再转十进制的过程出了问题……可是明明是机器告诉我有至少六位有效数字,那我输个六位有效数字的数不应该会出错的吧?
不知道哪位朋友能给我解答一下……是程序写错了吗?还是说有效数字的问题我理解错了?怎么样能让数值准确的输出呢?按照这种情况,岂不是大部分的运算的都是不准确的?
解决方案
float数据 机器内是2进制数,
1位符号位
8位指数位
23位“尾数”位
共32 位 2进制数。
平时讲 有效数字 是6~7位 ,指10进制。
通常程序输入的数是10进制,进入机器后要化成2进制,计算完又转十进制输出。
10进制到2进制,2进制到10进制 转换,有的数化不净,有的数化得净。
如同10进制分数化10进制小数,有的化得净(例如 4分之1,变0.25),有的化不净(例如 3分之1,变0.33333....)。
10进制到2进制,2进制到10进制 转换,化得净的效数字7位,化不净的效数字6位,因为最后一位有舍入误差。
例如:
float xy;
x=0.51; // 化不净
y=0.5; // 化得净
printf(""x=%.8f y=%.8""xy); // 输出 0.50999999 0.50000000
解决方案二:
有效数字是指,浮点数中表示尾数的二进制的多少,这个有效数字是二进制的,换算成10进制大概是*0.3(2^10 = 10^3)
解决方案三:
有效数字和保留6位小数没有任何关系。二进制和10进制转换不是一一对应的,可以有误差。
比如说,你有一个“3进制”的弹簧秤,它的刻度是1/3斤。那么它的有效精度是1/3斤。现在称出来是5/3斤,用10进制表示是1.66666666....
你不能说它的精度有那么高。
解决方案四:
这个要去看看IEEE标准。
解决方案五:
老实说,我都不清楚float还有有效位数FLT-DIG这个系统值,而细看float的存储方式,这个值的准确性实在难以保证。
我们都知道,float是用4个字节——相当于一个int的内存单元——来存储数值的,至于具体的存储细节,这篇转载的文章写得很清楚:http://blog.csdn.net/yezhubenyue/article/details/7436624,所以,如果要使用6位有效数字的计算,使用更高精度的double或其他类型,或者自行通过字符串来实现10进制的加减乘除,完全可以实现所需的精度需求(我记得大二时候有个作业就是实现大数计算,网上这方面的资料很多的)