老甲克C++随笔(oldjacky||oldjackyone)  
.........体验真实C++.........
公告
日历
<2010年2月>
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213
统计
  • 随笔 - 15
  • 文章 - 6
  • 评论 - 82
  • 引用 - 0

导航

最新闪存

搜索

 

常用链接

我参与的团队

随笔分类

随笔档案

文章分类

偶的好友链接

积分与排名

  • 积分 - 41615
  • 排名 - 1799

最新评论

阅读排行榜

评论排行榜

 

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

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

0
0
(请您对文章做出评价)
» 下一篇:宽字符输出
posted on 2004-06-09 11:45 oldjacky 阅读(1387) 评论(5)  编辑 收藏 网摘 所属分类: C++基础(原创)
评论:
  • #1楼  刘敏(Rustle Liu) Posted @ 2004-06-09 12:25
    http://blog.joycode.com/zhanbos/posts/19599.aspx
      回复  引用    

  • #2楼  周星星[未注册用户] Posted @ 2004-06-09 13:24
    1。改 float a=1.1 为 float a=1.1f,其他相同。
    2。浮点数本身就可能有精度损失,任何一本书上就会告诉你不应该直接比较。再看看 int i = 6.6/2.2; i == 2;
    3。计算机中的浮点数不满足很多定律
       float a = ?; float b = a; 这时 a 和 b 不是在所有机器上都相等
       a+(b+c) 也不一定等于 (a+b)+c,这就是为什么编译器不对浮点运算做优化的原因。
    4。没事看看我写的http://blog.vckbase.com/bruceteen/articles/240.aspx
    不过我还没写完。
      回复  引用    

  • #3楼  fff Posted @ 2004-06-20 12:21
    如果把数据类型都改成double那也不会出现warning,那是因为double是由编译器自己处理,但是在vc++6.0上只要把a改成double
    就可以使a=b 了这怎么解释呢?
      回复  引用    

  • #4楼  oldjacky Posted @ 2004-06-20 15:28
    译器把double数据都当做整数来处理,形式:1.1*(10的1次方),在编译器中表示为 11,1 表示出来的时候,就加上小数点,这样就避免了小数产生的误差,从而达到精确的形式   回复  引用    

  • #5楼  fff Posted @ 2004-06-20 20:22
    我说的是只把a改成double 而b依然是float的时候
    a+b赋值给b的时候,计算机只对a作了避免误差处理,而b
    好象没有,那他们的和赋值给b的时候是不是精确值呢?
    不明白,请指教~
      回复  引用    

 
Copyright © oldjacky Powered by: 博客园 模板提供:沪江博客