大家好,
今天碰到了一个问题,如下的代码:            float f1 = 935.5f;
            float f2 = 909.9f;
            Console.WriteLine(f1-f2);输出结果是:25.59998希望高手讲讲是什么原因,还有,如果我就是想简单得到:25.6  ,该怎么处理才能保证得到正确结果,并且比较通用,不仅仅是做1位的四舍五入?非常感谢。

解决方案 »

  1.   

    http://en.wikipedia.org/wiki/Floating_point如果把float转化为二进制存储(事实上,Float在存储的时候肯定是转换为字节形式的)
    就会存在
    value = significant digits × baseexponent 的问题
    也就会存在一定的偏差。
      

  2.   

    不是运算问题,而是由于float类型表示有效位数的能力有限,是无法精确的存储935.5或909.9的(因为转换为二进制存储的时候只能无限的近似),只能存一个近似值。  所以结果会有误差
      

  3.   

    float类型转换为二进制存储的时候无法精确
    因为二进制数值可以准确表示整数(可以使用整数转换为二进制方法验证下),所以可以将小数乘以10或100等变成整数,然后做运算,最后再通过除以10或100等获得结果
      

  4.   

    换用double或是结果处理一下,比如增加一个微小量。
      

  5.   

    http://hi.baidu.com/libinguest/blog/item/1e983fd34d5d0e093af3cfa0.html
      

  6.   

    在Math里有Math.Round方法试一下
      

  7.   

    在Math类里有Math.Round方法试一下
      

  8.   


                double d1 = 935.5;
                double d2 = 909.9;
                Console.WriteLine(d1 - d2);  //25.6
      

  9.   

    decimal f1 = 935.5m;
    decimal f2 = 909.9m;
    decimal f = f1 - f2; //f=25.6
      

  10.   


                float f1 = 935.5f;
                float f2 = 909.9f;
                Console.WriteLine((f1 - f2).ToString("0.0"));  //25.6
      

  11.   

    float 类型 是32 位的  
      

  12.   

    float f1 = 935.5f;
                float f2 = 909.9f;
                Console.WriteLine((f1 - f2).ToString("0.0"));  //25.6
      

  13.   

    float 与计算机中数值表示方法有关,不是准确数据
    使用double
      

  14.   

    谢谢大家的回复,
    总结来说,
    就是一句话,float精度不够,运算会出问题,建议用 double,decimal
    可是问题是  float 连这么简单个问题都处理不了,存在还有啥意义呀。
    并且前面大家指教的一些方法: *10,再 /10 或者用 ToString("0.0") 这些之类的,都不通用呀,还得做小数位数的判断。比起这个问题的简单,常见程度来,我们解决它的方法是多么地费力。如果说是计算机的问题,我试了C++的同样程序,同样的数值,同样的float 型,为啥就好好的25.6结果就出来了呢?希望能继续得到大家的帮助
      

  15.   


    static void Main(string[] args)
    {
        float f1 = 935.5f;
        float f2 = 909.9f;
        float f3 = f1 - f2;
        Console.WriteLine(f3);
        Console.ReadKey();
    }//输出
    25.59998
    //调试看到f3
    25.5999756int main()
    {
        float f1 = 935.5f;
        float f2 = 909.9f;
        float f3 = f1-f2;
        cout<<f3;
        cin.get();
        return 0;
    }//输出
    25.6
    //调试看到f3
    25.599976结论:
    和语言无关。
    估计cout的<<方法有优化。
      

  16.   


    大家给出的方法为什么不能用,Math.Round() 就是一个很通用的阿你说的C++程序能够出来,因为cout的时候会根据输出会根据你输入的精度做一个判断
    如果两个的精度不一致你再看看,
    cout << fixed << setprecision(4)  c++也有这种方式来控制精度的。
      

  17.   

    楼上的大哥,谢谢你的回复Math.Round()的不通用我指的是在用的时候要指定精确的位数(据我所知好像是必须得指定吧),
    但是,这个位数怎么来的呢?我前面例子是1位就够了,但是我并不知道每次那个float型倒底值会是几位,
    下次如果是 1998.255-1909.268 ,这次我要指定精度就为3了。也就是说每次都要加一个额外的判断来判断需要精确的位数。这就是我说的不通用,费力的原因。你提到的:“你说的C++程序能够出来,因为cout的时候会根据输出会根据你输入的精度做一个判断
    如果两个的精度不一致你再看看,”
    这个麻烦详细讲一下可以吗?我前面的示例中没有指定cout的精度呀,但输出是正确的,我也如前面朋友所讲的调试时看了一下,确实也是不精确的,确实是cout自己进行了优化,既然cout都能优化,为啥不直接在计算结果中就优化成正确的值呢。。更加感觉郁闷了,那这个float型真是废柴呀
      

  18.   

    用decimal,调试和运行的结果同为25.6
      

  19.   

    恩,确实如楼上所说,上面的情况 decimal 是可以正常运行的,但是能保证所有的decimal值都能运算正常么?(除了溢出这种必然的异常以外)。
      

  20.   

    在C#里面你用这个试试
    float f1 = 935.59f;
    float f2 = 909.9f;
    然后你看看
    再用
    double f1 = 935.59;
    double f2 = 909.9;

    double f1 = 935.5;
    double f2 = 909.9;三个结果你对比看看就知道了。 因为在转换二进制的时候,很有可能最后一位会有一个1,这样导致编译输出时系统无法知道你是否需要截断尾部,必须要你自己手动来指定,没人敢确定你就是只需要输入的精度。
      

  21.   

    恩,谢谢 waywander 兄,我不知道你的意思是不是:
    “如果能确定两个操作数的小数位数,那么就可以确定结果需要精确到的位数,
    但现在的问题是,两个操作数本身存储就没有精确的位数可言,因此,编译器无法判断得到结果位数的精度,而必须自己手动指定。”我不是很清楚你说的很有可能最后一位会有一个1怎么就会影响对位数的判断了。但是我们显然看到,C++中的cout 跟 Python 中的 print 是完全可以正确的打印出准确结果来的,说明编译器是有方法判断用户所需要精度的!并且现在的问题是,这并不是一个非正常结果,不是1/3之类,或者是要溢出的运算,这只是非常普通的一类,绝对能得到准确结果的运算。而我们非常尴尬的得到了一个错误的结果
      

  22.   

    使用decimal,而少用float,浮点、浮点----浮动的点当然是不稳定滴