为什么Math.Round / Floor / Ceiling不返回long或int?

时间:2010-08-14 01:56:13

标签: c# .net

每次时间我使用Math.Round/Floor/Ceiling我总是强制转换为int(或者如果需要,可能long)。如果它总是返回一个整数,为什么它们会返回double

4 个答案:

答案 0 :(得分:29)

结果可能不适合int(或long)。双倍的范围要大得多。

双倍的近似范围:±5.0×10 -324 至±1.7×10 308

(Source)

答案 1 :(得分:8)

我同意Mark的回答,结果可能不适合long,但您可能想知道:如果C#的long类型更长,该怎么办?好吧,这是Python中使用它的任意长度整数发生的事情:

>>> round(1.23e45)
1229999999999999973814869011019624571608236032

大多数数字都是浮点舍入误差的“噪音”。在{C#中Round / Floor / Ceiling返回double的动机的一部分动机可能是为了避免错误精确的错觉。

另一种解释是.NET Math模块使用用C编写的代码,其中floorceil返回浮点类型。

答案 2 :(得分:2)

除了范围参数之外,这些答案中没有一个解决了当你真正需要精确整数时返回浮点数的基本问题。在我看来,通过小的舍入误差计算的浮点数可能小于或大于所需的整数,因此转换操作可能会产生一个错误。我认为,您需要将整数(不是双倍)舍入函数应用于floor()的双重结果,而不是强制转换。或者编写自己的代码。无论如何,floor()ceil()的C库版本都非常慢。

这是真的,还是我错过了什么?在IEEE浮点标准中有一些关于整数的精确表示,但我不确定这是否使得转换安全。

我宁愿在函数中进行范围检查(如果需要避免溢出)并返回long。对于我自己的私人代码,我可以跳过范围检查。我一直这样做:

long int_floor(double x)
{
    double remainder;
    long truncate;
    truncate = (long) x;        // rounds down if + x, up if negative x
    remainder = x - truncate;   // normally + for + x, - for - x
    //....Adjust down (toward -infinity) for negative x, negative remainder
    if (remainder < 0 && x < 0)
        return truncate - 1;
    else
        return truncate;
}

对于ceil()round()存在对应部分,对负数和正数有不同的考虑。

答案 3 :(得分:-2)

我无法找到可以找到的文档。我最好的猜测是,如果你正在使用双打,很可能你会想要对双打进行任何操作来返回双精度。对它进行舍入以转换为int被语言设计者认为不那么常见,然后舍入并保持为双倍。

您可以编写自己的方法,在大约2行代码中将它转换为int,并且比在堆栈溢出上发布问题要少得多......