一、请先看以下的一段代码:
int main()
{
float a=1.1;//①warning : truncation from 'const double' to 'float'
float b=1.2;//②warning : truncation from 'const double' to 'float'
float c=2.3;
b=a+b;
cout<<sizeof(float)<<endl;//③
cout<<"c="<<c<<" "<<"b="<<b<<endl;
if(c==b)//④
cout<<"b与c相等."<<endl;
else
cout<<"b与c不相等."<<endl;
return 0;
}
解释:1) 在①处我们可以看到一个错误提示"将data区的double型数据转成float将切断double的长度"
2) 在②处是与①同样的效果.
3) 我们在④处看到了一个并不愿意看到的结果,输出"b与c不相等.".
二、理解代码简单工作原理
我们以16位系统为一个对照,float的数据类型所占的字节为4(在③处输出可以看到),为32位,我们先把十进制1.1转换成二进制表示(利用“乘2取整法”):
小数部分:
----------------------------------------------------------
0.1*2=0.2------0(整数部分)
0.2*2=0.4------0(整数部分) A
0.4*2=0.8------0(整数部分)
----------------------------------------------------------
0.8*2=1.6------1(整数部分)
0.6*2=1.2------1(整数部分)
0.2*2=0.4------0(整数部分) B
0.2*2=0.4------0(整数部分)
0.4*2=0.8------0(整数部分)
-----------------------------------------------------------
0.8*2=1.6------1(整数部分)
0.6*2=1.2------1(整数部分)
0.2*2=0.4------0(整数部分) C(出现循环B)
0.2*2=0.4------0(整数部分)
0.4*2=0.8------0(整数部分)
-----------------------------------------------------------
.
.
.
我们看到把1.1转换成二进制时出现循环体(即:小数部分出现循环),在VC中默认的静态浮点数为double型(即1.1在默认的情况下是double型),那么就会把多出32位的位值删除,取得一个这么一个32位的二进制代码来赋给a,此时a的值已不再是十进制的1.1,而是近似1.1的一个值。在输出设备中我们看到的是两个同样的值,这是编译器进行近似取值的原因。包括1.2也是如此(您不防试着转换一下看看)。
我们如果改成以下的赋值那就不会出现以上的warning,道理也很简单,因为1.5正好可以在32位中进行转换完全,所以并不存在数据丢失,而取近似值的问题。
int main()
{
float a=1.5;//OK
float b=1.5;//OK
float c=3.0;
b=a+b;
cout<<sizeof(float)<<endl;
cout<<"c="<<c<<" "<<"b="<<b<<endl;
if(c==b)
cout<<"b与c相等."<<endl;//预期的结果
else
cout<<"b与c不相等."<<endl;
return 0;
}
三、最后一步
我们如果把数据类型都改成double那也不会出现warning,那是因为double是由编译器自己处理,编译器把double数据都当做整数来处理,形式:1.1*(10的1次方),在编译器中表示为 11,1 表示出来的时候,就加上小数点,这样就避免了小数产生的误差,从而达到精确的形式;float是32位,将采用cpu处理方式,转换成二进制代码取近似值;
最后,要提的是float是32位,是用cpu处理,速度较快;而double是64位,则先用编译器来进行处理,处理完后再用cpu按整型数据处理并转换成二进制代码存贮;那相比之下,float要比double要快。