为什么Math.Round / Floor / Ceiling不返回long或int?
每次我使用Math.Round/Floor/Ceiling
我总是转换为int
(或者如果需要可能long
)。 如果它总是返回一个整数,为什么它们会返回double
。
结果可能不适合int(或long)。 双倍的范围要大得多。
双倍的近似范围:±5.0×10 -324至±1.7×10 308
(资源)
我同意Mark的回答,结果可能不适合很long
,但你可能想知道:如果C#有更长的类型怎么办? 好吧,这是Python中使用它的任意长度整数所发生的事情:
>>> round(1.23e45) 1229999999999999973814869011019624571608236032
大多数数字是来自浮点舍入误差的“噪声”。 Round
/ Floor
/ Ceiling
在C#中返回double
的动机的一部分可能是为了避免错误精确的错觉。
另一种解释是.NET Math
模块使用用C编写的代码,其中floor和ceil返回浮点类型。
除了范围参数之外,这些答案都没有解决当我真正想要一个精确整数时返回浮点数的基本问题。 在我看来,计算的浮点数可能小于或大于所需的整数一个小的舍入误差,因此转换操作可能会产生一个错误。 我认为,你需要将一个整数(不是双倍)舍入函数应用于floor()
的double结果,而不是强制转换。 或者编写自己的代码。 无论如何, 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()
存在对应部分,对负数和正数有不同的考虑。
对于我能找到的文档没有任何理由。 我最好的猜测是,如果你正在使用双打,很可能你会想要对双打进行任何操作来返回双精度数。 对它进行舍入以转换为int被语言设计者认为不那么常见,然后舍入并保持为双精度。
您可以编写自己的方法,在大约2行代码中将它转换为int,并且比在堆栈溢出上发布问题要少得多…