请大家帮忙看一下以下程序:
#include<stdio.h>
void main()
{
char *buffer=new char[30];
floatfp=333.3333;
sprintf( buffer , "%f", fp );
printf("%s",buffer);
}
为什么输出是:333.333313呢?后面多出来的13是怎么回事啊?
但是如果把float改成double就没有错误了,这是为什么呢?
解析:
关于float与double结果的误差
假设有一道题:
float a;
a=123456.789e5;
System.out.printf("%f\n",a);
结果是:
12345678848.0000006
而不是:12345678900.000000
分析:由于float在内存中占4个字节(32 bit),对于这个数来说会有数据丢失。实型数据是按照指数形式存储的。系统把一个实型数据分成小数部分和整数部分分别存放。在4个字节中,究竟用多少位来表示小数部分,多少位来表示指数部分,对于不同编译器可能会有不同。多数是以3 byte (24 bit) 表示小数部分(包括符号),以1 byte (8 bit) 表示指数部分(包括指数的符号)。
看看浮点数是怎样炼成的,呵呵:
12345678900(十进制)=>
1011011111110111000001110000110100(34位精确值)
========>
符号位:0
尾数:1.01101111111011100000111(取24位)
=>(注意:前面的1在实际存放时为了多存放一位而隐含,即浮点数的尾数的最高位永远隐含为1)
0 10100000 01101111111011100000111(实际放了尾数后面的23位)
指数尾数
最后结果就是0101000000110111111101110000011
现在再把它还原成整数:
(1)取尾数23位:01101111111011100000111
(2)在前面加上隐含的1,变成:101101111111011100000111
(3)取指数8位:10100000
(4)指数减127得:100001(33)
(5)尾数向左移动10位(尾数本身23位,33-23=10):1011011111110111000001110000000000
此即12345678848
启示:在需要精确答案的地方,要避免使用float和double;对于货币计算,要使用int、long(把零钱换成分来表示,这时就没有小数位,然后结果再除以相应的权值.)或BigDecimal。