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

问题描述 投票:0回答:4

每次使用

Math.Round/Floor/Ceiling
时,我总是投射到
int
(或者如果需要的话可能是
long
)。如果总是返回整数,为什么它们会返回
double

c# .net
4个回答
32
投票

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

双精度的近似范围:±5.0 × 10−324 至 ±1.7 × 10308

(来源)


8
投票

我同意 Mark 的回答,即结果可能不适合

long
,但您可能想知道:如果 C# 有更长的
long
类型怎么办? 好吧,这就是 Python 中使用任意长度整数时发生的情况:

>>> round(1.23e45)
1229999999999999973814869011019624571608236032

大部分数字都是来自浮点舍入误差的“噪声”。 也许

Round
/
Floor
/
Ceiling
在 C# 中返回
double
的部分动机是为了避免错误精度的错觉。

另一种解释是.NET

Math
模块使用用C编写的代码,其中floorceil返回浮点类型。


2
投票

抛开范围参数不谈,这些答案都没有解决对我来说,当你真正想要一个精确的整数时返回浮点数的基本问题。 在我看来,计算出的浮点数可能会小于或大于所需的整数一个小的舍入误差,因此强制转换操作可能会产生一个误差。我认为,您需要将整数(非双精度)舍入最近函数应用于

floor()
的双精度结果,而不是强制转换。 或者编写自己的代码。无论如何,C 库版本的
floor()
ceil()
都非常慢。

这是真的吗,还是我错过了什么? 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()
的对应项,对负数和正数有不同的考虑。


-2
投票

我能找到的文档中没有给出任何原因。我最好的猜测是,如果您正在使用双打,您很可能希望对双打进行任何操作都返回双打。语言设计者认为将其舍入到 int 比舍入并保留为 double 更不常见。

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

© www.soinside.com 2019 - 2024. All rights reserved.