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
- 演员应在乘法后进行评估。
答案 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.为什么?从浮点(double
或float
)到int
的转换会截断小数部分。它不圆。所以它切断了.9999而你得到了108。
要舍入,请按Math.Round()
或Convert.ToInt32()
替换广播。
Convert.ToInt32((float) 10.9 * 10);