代码之家  ›  专栏  ›  技术社区  ›  zhy2002

为什么(双倍)0.6f>(双倍)(6/10f)?

c#
  •  10
  • zhy2002  · 技术社区  · 14 年前

    在我的电脑上会发生这样的情况:

    (double)(float)0.6
    = 0.60000002384185791
    
    (double)0.6f
    = 0.60000002384185791
    
    (double)(6/10f)
    = 0.6
    
    (double)(float)(6/10f)
    = 0.6
    


    在我看来(双倍)(6/10f)也应该是0.60000002384185791。

    3 回复  |  直到 14 年前
        1
  •  5
  •   Justin    14 年前

    首先,重要的是要记住 0.6 float 可以 准确地表示为 double 0.6 this link )

    您看到上述行为的原因在于编译器—如果您在reflector中查看编译的程序集,那么这里发生的事情就更清楚了:

    ( 我把代码改了,这样就不用了 Console.WriteLine ,因为我意识到编译器正在为您选择一个重载,这混淆了情况)

    // As written in source
    var j = (double)(float)0.6;
    var k = (double)0.6f;
    var l = (double)(6/10f);
    var m = (double)(float)(6/10f);
    
    // Code as seen by Reflector
    double j = 0.60000002384185791;
    double k = 0.60000002384185791;
    double l = 0.6;
    double m = 0.6;
    

    其他一些有趣的案例:

    // Code
    var a = 0.6;
    var b = (double)0.6;
    var c = 0.6f;
    var d = (float)0.6;
    
    var e = 6 / 10;
    var f = 6 / (10f);
    var g = (float)(6 / 10);
    var h = 6 / 10f;
    var i = (double)6 / 10;
    // Prints out 0.60000002384185791
    
    double n = (float)0.6;
    double o = f;
    
    // As seen by Reflector
    double a = 0.6;
    double b = 0.6;
    float c = 0.6f;
    float d = 0.6f;
    
    int e = 0;
    float f = 0.6f;
    float g = 0f;
    float h = 0.6f;
    double i = 0.6;
    
    double n = 0.60000002384185791;
    double o = f;
    

    编译器似乎只在几个特殊情况下才执行上述技巧,为什么它只在转换为double时执行此操作我完全不明白!

    剩下的时间,它似乎做了一些骗局,使浮点运算 似乎

        2
  •  2
  •   Robert Harvey    14 年前

    结果似乎是四舍五入。您是否用必要的精度数字显示结果?你可以用 this c# class

    ToString() 不会总是打印所有数字,VisualStudio调试器也不会。

        3
  •  1
  •   Stan Rogers    14 年前

    如果我是一个赌徒,我会说不同的是在哪里发生的胁迫。在后两个例子(6/10f)中,有两个文字都是整数(整数6和浮点10.00000000…)。除法似乎是在强制之后发生的,至少在您使用的编译器中是这样。在前两个示例中,您有一个分数float literal(0.6),它不能充分地表示为float尾数内的二进制值。将该值强制为double不能修复已经造成的损坏。