理解给定的计算(cast + multiplication)

时间:2015-11-04 06:26:57

标签: c# .net casting

if (isset($_POST["events"])&&isset($_POST["description"])) 
            {
                $id=mysql_real_escape_string(trim($_POST["id"])); 
                $title=mysql_real_escape_string(trim($_POST["events"]));
                $description=mysql_real_escape_string(trim($_POST["description"]));
              }

评估为(int)((float)10.9 * 10) 。为什么呢?

IMO 108 - 演员应在乘法后进行评估。

3 个答案:

答案 0 :(得分:11)

有趣的是,这里的问题是表达式是在编译时计算的,显然是按预期使用单精度数学。这在调试和发布版本中都会发生:

    // this replaces the whole operation
    IL_0001: ldc.i4.s 108
    IL_0003: stloc.0
    IL_0004: ldloc.0
    IL_0005: call void [mscorlib]System.Console::WriteLine(int32)

虽然案例var f =((float)10.9 * 10);int i = (int)f;仍然针对乘法进行了优化,但使用了双精度。因为演员表是在一个单独的步骤中完成的,我猜它会混淆编译器(??):

    IL_000b: ldc.r4 109      // 109 result for the first part
    IL_0010: stloc.1
    IL_0011: ldloc.1
    IL_0012: conv.i4         // separate conversion to int
    IL_0013: stloc.2
    // rest is printing it
    IL_0014: ldloc.1
    IL_0015: box [mscorlib]System.Single
    IL_001a: ldstr " "
    IL_001f: ldloc.2
    IL_0020: box [mscorlib]System.Int32
    IL_0025: call string [mscorlib]System.String::Concat(object, object, object)
    IL_002a: call void [mscorlib]System.Console::WriteLine(string)

老实说,我会说编译器在第二种情况下生成了错误的代码,这可能就是为什么C ++避免优化像瘟疫那样的浮点代码。幸运的是,这只是这种测试代码的一个问题,可以在编译时完全完成,实际的变量乘法就可以了。

我实际上也试过这个:

Console.WriteLine((int)(float.Parse(Console.ReadLine()) * int.Parse(Console.ReadLine())));

并给出了10.9和10,结果是预期的108.

答案 1 :(得分:10)

情况确实如此。由于浮点数的表示方式(10.9不能精确表示,所以你得到一个近似值,在这种情况下是10.89999999 ...),只是因为10.9 小于10.9。 。然后,强制转换会截断小数点后面的任何数字。所以你得到108。

此处的确切值如下(使用Jon Skeet的DoubleConverter类获得):

10.9         -> 10.9000000000000003552713678800500929355621337890625
(float) 10.9 -> 10.8999996185302734375

将浮动乘以10,然后切掉所有小数位,显然会导致108。

答案 2 :(得分:2)

在转换为int之前,您的float结果为108.9999,因为109.0000 can't be represented in floating point(如评论中所述,这是错误的; 109可以很好地表示,但不知何故表达式结果为108.9999 - 以下仍然适用)

int值为108.为什么?从浮点(doublefloat)到int的转换会截断小数部分。它不圆。所以它切断了.9999而你得到了108。

要舍入,请按Math.Round()Convert.ToInt32()替换广播。

Convert.ToInt32((float) 10.9 * 10);