老甲克C++随笔(oldjacky||oldjackyone)  
.........体验真实C++.........

一、请先看以下的一段代码:

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要快。

posted on 2004-06-09 11:45  oldjacky  阅读(2371)  评论(5编辑  收藏  举报