float a = 3f;
for(int i=0;i<200;i++)
    a-=0.01;
a = (int)a;
System.out.println(a);//结果是什么,说明原因.

解决方案 »

  1.   

    结果肯定是1。0,过程中出现的00001,我的理解是计算机的二进制与我们用的10进制转换问题。(个人理解)
    就像DOUBLE的0。0无限接近于0一样
      

  2.   

    楼主你是不是搞错了啊
    怎么会输出那么多次啊a = (int)a;
    其中(int)a ==1 是可以确定了
    为什么输出是1.0呢,是因为a是float型的
    这句的效果就是 float a =1 一样
      

  3.   

    a = (int)a;这里我也有点不明白,为什么经过 (int) 转换了 还是  1.0 呢,还会有小数位呢?
      

  4.   

    1.0,(int)a的确为1,可是a是float类型的啊,就相当于float a=1一样,那a就是1.0了.
      

  5.   

    输出是1.0
    虽然(int)a=1,但a仍然是float的啊!所以输出为1.0
    人类使用的是十进制,所以你觉得a的结果为1.0,但计算机用的是二进制啊,结果a等于1.0000009,就好比你没法用十进制精确得表示1/3一样!
      

  6.   

    float a = 3f;
    for(int i=0;i<200;i++)
        a-=0.01;
    a = (int)a;
    System.out.println(a);//为什么那么多人不理解结果是1.0呢??程序中的a是float类型,它是全局的,
    a = (int)a;    
    实际上是:float a = (int)a; 
    等式右边强制类型转换(float-->int),所以结果是1,而等式左边,由于a是float类型,将int行赋值给float类型,就发生了自动类型(隐式类型转换)转换了(int-->float);所以结果是1.0;至于在计算过程中为什么出现;第 9 次=====2.9
    第 10 次=====2.89
    第 11 次=====2.88
    第 12 次=====2.8700001
    第 13 次=====2.8600001我也同意是计算机进制之间转换的问题
      

  7.   

    float a = 3f;
    for(int i=0;i<200;i++)
    a-=0.01;在这个计算过程中有没有方法测算出任一次循环后a的值呢?
      

  8.   

    float a = 3f;
    for(int i=0;i<200;i++)
        a-=0.01;
    a = (int)a;
    System.out.println(a);//楼主题目都写错了。。如果结果是你这样的话:
    ......
    ......
    第 9 次=====2.9
    第 10 次=====2.89
    第 11 次=====2.88
    第 12 次=====2.8700001
    第 13 次=====2.8600001
    .....那么就要注释这一句 //a = (int)a;
    结果是1.000019
    应该是十进制和二进制转换之间出现的问题哦。。
      

  9.   

    在这个计算过程中有没有方法测算出任一次循环后a的值呢?-------------------------------------------------------------晕。。要看的话就在FOR里面加条件咯。。
      

  10.   


    在这个计算过程中有没有方法测算出任一次循环后a的值呢?-------------------------------------------------------------晕。。要看的话就在FOR里面加条件咯
    ===================================================================================
    怎么加?
    ......
    ......
    第 9 次=====2.9
    第 10 次=====2.89
    第 11 次=====2.88
    第 12 次=====2.8700001
    第 13 次=====2.8600001
    .....
    这是我测试打印的中间值,大家都认为是"十进制和二进制转换之间出现的问题",是怎样的问题呢?如果在没运行程序前是否能判断出第97次后的值呢?
      

  11.   

    楼主:最后你的变量a还是是Float啊
      

  12.   

    float a;
    ......
    (a = (ing)a;) 和(float a = (int)a)
      

  13.   

    应该是1.0吧,虽然没有运行测试过因为3-1.99后取整数部分同时a又是float类型
      

  14.   

    200的循环。。
    将结果float type casting int  再赋值给float type 。
    结果是多少我就不想去计算了。。
      

  15.   

    现在看来大家对输出结果为1.0是没有异议了,现在的疑点是输出的过程为什么会出现小数点后n个数字了.我觉得除了计算机进制的转换问题是有很大的关系的,我想这一点是肯定;还有一个比较重要的因素,就是cpu(硬件)结构也有一定的关系;最后一点,也是最重要的,也许弄懂了这一点,大家就会明白了计算过程出先的情况了-----float类型的精度问题,只要是数据类型是有精度的,类似的计算都会出现这样的情况.不信可以将float换为double试试:
    double类型的输出结果:第 0 次     2.99
    第 1 次     2.9800000000000004
    第 2 次     2.9700000000000006
    第 3 次     2.960000000000001
    第 4 次     2.950000000000001
    .......
    .......
    精度越大的输出的位数越多.什么原因,这就是double的精度比float高的原因.至于计算过程为什么会有2.950000000000001这种情况出现,我想无非就是上面我说的三种情况,其中最位关键的是第三种--计算机中的浮点数怎么表示的(这里我不再细细说明,想深入理解的话,可以去看 "计算机原理" 这门课程,或者去看看 "IEEE754标准" 中怎么定义的):java也是采用IEEE754标准来表示浮点数, 根据IEEE的标准,浮点数的定义如下:
    在数字中,表示一个浮点数需要三要素:尾数(Mantissa)、指数(Exponent,又称为阶码)和基数(Base)。任意一个浮点数N可以表示成下列形式:N = M × BE,例如N(10) =1.234×10-6, N(2)= -0.001011×2011等.M和E决定了浮点数的精度(precision),E指明小数点在B进制数据中的位置,因而E和B决定了浮点数的表示范围(range),浮点数的符号(Sign)是单独考虑,表示为:
                               ______________________________                         
                               |符号位(S) | 阶码(E) | 尾数(M)|
                               ------------------------------
         为便于软件的移植,浮点数的表示格式应该有统一标准。1985年IEEE(Institute of Electrical and Electronics Engineers)提出了IEEE754标准。该标准规定基数为2,阶码E用移码表示,尾数M用原码表示,根据原码的规格化方法,最高数字位总是1,该标准将这个1缺省存储,使得尾数的表示精度多了一位。实数的IEEE754标准的浮点数格式为:____________________________________________________________________________
    |                  |                  存储位数           |    |偏移量 |
    |类型              |---------------|------------|--------------|总位数 | offset |
    |                  |      数位(S)  |   指数位(E)| 小数部分(M)  |       |        |
    |------------------|---------------|------------|--------------|-------|--------|
    |单精度浮点数float |     1 位      |    8位     |   23位       |   32   | 127    |
    |------------------|---------------|------------|--------------|--------|--------|
    |双精度浮点数double|     1 位      |    11 位|  |   52位       |   64   | 1023   |
    |----------------------------------|------------|--------------|--------|--------|
    说明:   1) 约定小数点左边隐含有一位1,实际上使尾数的有效位数为24位,即尾数为1.M
       2) 偏移值 = 2 ^ (尾数位数 - 1) – 1。必须从指数中减去偏移值,才能确定有符号指数的实际值。
       3) 讨论float型:
          E = 0, M = 0 , 若 S = 0, 则N = 0;  S = 1, 则 N = -0。-0可以表示一个很小的数,小到在单精度格式中不能
    用数字和指数来表示。尽管如此,它们然小于0。
          E = 0, M ≠ 0, 则数是有效的,但不是规格化数, N =  (-1) ^ S × 2 ^ ( - 127) × (0.M)
          E = 255, M = 0, 则数为正或负无穷大, 这取决于S.
          E = 255, M ≠ 0, 则N不是一个数,  表示为NaN.
          E = 1 ~ 254,  则N = (-1) ^ S × 2 ^ (E - 127) × (1.M), 为规格化数.规格化表示
           java中的浮点数采用的事IEEE Standard 754 Floating Point Numbers标准,         
           
           float占用4个字节,和int是一样,也就是32bit.
           第1个bit表示符号,0表示正数,1表示负数,这个很好理解,不用多管.
           第2-9个bit表示指数,一共8为(可以表示0-255),这里的底数是2,为了同时表示正数和负 
                数,这里要减去127的偏移量.这样的话范围就是(-127到128),另外全0和全1作为特
                殊处理,所以直接表示-126到127. 剩下的23位表示小数部分,这里23位表示了24位的数字,因为有一个默认的前导1(只有二进制才有这个特性). 最后结果是:(-1)^(sign) * 1.f * 2^(exponent) 这里:sign是符号位,f是23bit的小数部分,exponent是指数部分,最后表示范围是(因为正负数是对称的,这里只关心正数)2^(-126) ~~ 2(1-2^(-24)) * 2^127这个还不是float的取值范围,因为标准中还规定了非规格化表示法,另外还有一些特殊规定.
        
    非规格化表示:
        当指数部分全0而且小数部分不全0时表示的是非规格化的浮点数,因为这里默认没有前导1,而是0. 取值位0.f * 2^(-126),表示范围位 2^(-149)~~ (1-2^(-23)) * 2^(-126) 这里没有考虑符号.这里为什么是-126而不是-127? 如果是-127的话,那么最大表示为2^(-127)-2^(-149),很显然2^(-127) ~~2^(-126) 就没法表示了. 其他特殊表示
        1.当指数部分和小数部分全为0时,表示0值,有+0和-0之分(符号位决定),0x00000000表示正0,0x80000000表示负0.
        2.指数部分全1,小数部分全0时,表示无穷大,有正无穷和负无穷,0x7f800000表示正无穷,0xff800000表示负无穷.
        3.指数部分全1,小数部分不全0时,表示NaN,分为QNaN和SNaN,Java中都是NaN.------------------------------------------
    建议在程序中,对浮点数进行判断时,如果有一值是通过运算得来的,最好不要用他们作为条件判断,否则你会得到异想不到的结果.
     如
        double a = 3.0;
            double b =2.95.
            for (int i = 0; i < 15 ;i++)
               a-=0.01;
            if (a == b ) //通常认为肯定会相等,条件值肯定ture,但是实际运行却不是,当然
                ......  //这不是你的错,是计算机的错.计算机结果是近似取近似值,而判断      ....//却是精确值
            else
                ......
      

  16.   

    我举个例子:
      java的例子可能不好看,因为class文件不号看.我们就看看c环境下的一个程序:main()
    {
      float f=123.456;
      printf("f=%f\n",f);
    }一般认为都是输出123.456,实际是123.456001;这是c的最大精度吧,很久没有碰c了,c中float好像是双字节.
    我们来看看是怎么得出的,当然是按我上面写的方法来了:
    我们去看看编译后的文件,有一条汇编语句:00401028 mov dword ptr [ebp-4],42F6E979h
    其中十六进制数42F6E979h就是我们程序中的123.456;
    十六进制值42F6E979h由何而来?
              十进制           二进制
    N(10)=123.456=111011.01110100101111001= 1. 11101101110100101111001(...) * 2^6= N(2)
    , 那么E – 127 = 6;  E = 127 + 6 = 133(10) = 10000101(2),
    M = 111 0110 1110 1001 0111 1001 (省略了最高数字位1, 共23bit)组合起来就是:
    S          E                        M
    0        10000101      111 0110 1110 1001 0111 10014bit一间隔还成十六进制:
    0100   0010   1111   0110   1110   1001   0111   1001
     4       2      F     6      E      9       7      9  = 42F6E979H
     
      再由42F6E979h还原为float型取出十六进制数42F6E979h, 化为二进制为
    0*100 0010 1*111 0110 1110 1001 0111 1001(*为区分点)
    s=0, E=133, M=(1/2+1/4+1/8+1/32+1/64+1/256+1/512+...)=0.92900002002716064453125N=1*64*(1+0.92900002002716064453125)=123.45600128173828125123.456 约等于 123.456001 约等于 123.456001 28173828125
      

  17.   

    明白了,但还想问yanhuaxie(IT Farmer)一个问题,您别笑我太苯啊~~在你的例子里:
    “double a = 3.0;
            double b =2.95.
            for (int i = 0; i < 15 ;i++)
               a-=0.01;
            if (a == b ) //通常认为肯定会相等,条件值肯定ture,但是实际运行却不是,当然
                ......  //这不是你的错,是计算机的错.计算机结果是近似取近似值,而判断      ....//却是精确值”
    如果在程序中真的需要A和B的比较得到一个布尔值,应该怎么做呢??
      

  18.   

    测试一下,就知道了class Test
    {
    public static void main(String[] args)
    {float a = 3f;
    for(int i=0;i<200;i++)
        a-=0.01;
    a = (int)a;
    System.out.println(a);
    }
    }
      

  19.   

    shichunzhidezhanghu()的问题:标准的float型与“零值”比较的 if 语句可以这样写:
    const float EPSINON = 0.00001;
    if ((x >= - EPSINON) && (x <= EPSINON)
    注:不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”此类形式。类推一下a和b相比只要加个偏移就行了