为什么Math.Round不返回整数?

41
在C#中,为什么舍入数学函数Floor、Ceiling和Round不返回int?考虑到函数结果总是整数,为什么要返回floatdoubledecimal呢?

1
Round被重载了,对于初始值,返回类型必须匹配;p - leppie
13
想象一下,如果你调用Math.Round(1E30)并且它返回一个int,会发生什么? - Alvin Wong
那么你的意思是BCL应该确定你想要的结果吗? - Simon Whitehead
3
Math.Round() 返回与其参数相同类型是有道理的。更好的问题是为什么没有 Math.RoundToInt32Math.RoundToInt64Math.FloorToInt32Math.FloorToInt64 函数。 - supercat
性能和稳定性。 - aj.toulan
3个回答

37

double的范围为±5.0 × 10−324 到 ±1.7 × 10308,而long的范围为–9,223,372,036,854,775,808到9,223,372,036,854,775,807。不幸的是,并非所有整数浮点值都能由整数表示。

例如,1e19已经超过了64位有符号整数的范围。

(long)Math.Round(1e19) == -9223372036854775808L // WTF?

虽然单参数重载Math.Round(double)Math.Round(decimal)总是返回一个整数值,但是这些重载仍然不能返回整数值类型。

如果你知道传递给函数的值可以表示为整数值类型,那么你可以自己进行强制转换。库不会这样做,因为它需要考虑一般情况。


3
请注意,有些长整数无法用双精度浮点数表示:(double)100000000000000001L == 1e17(同时 1e17 == 1e17+1)。 - Antal Spector-Zabusky
@AntalS-Z 是的。为了更高的精度,最好使用 decimal 类型。 - Alvin Wong

13
考虑到该函数的结果始终为整数。
不,它并不是。你甚至可以使用Math.Round Method (Double, Int32)指定小数位数。
小数位数类型:
System.Int32
返回值中的小数位数。

2
+1 实际上,并不是所有情况下我们都需要四舍五入到整数。 - V4Vendetta
我在这里感到很困惑,Round的文档中说“返回最接近a的整数”,而你却说它并不总是返回整数。这似乎没有意义。 - PandaWood
@PandaWood,你在哪里看到“返回最接近的整数”?我找不到它,你能分享一下链接吗?如果你指的是这个 The integer nearest a. If the fractional component of a is halfway between two integers, one of which is even and the other odd, then the even number is returned. Note that this method returns a Double instead of an integral type. 那么请注意最后一部分。 - Habib
@Habib 好的,谢谢,不知道为什么我没看到最后一部分。 - PandaWood

2

这是为了包含比int范围更大的数字。所以Math.Floor会返回一个double类型,根据大小和开发人员的需要,可以将其转换为int或long类型。 如果你尝试在int范围之外使用Math.Floor,如果Math.Floor返回int类型,它将失败,但它不会,它返回一个double类型,你可以将其转换为long类型。

     double d = 4147483647.5678;
     long a = (long)Math.Floor(d);
     int b = (int)Math.Floor(d);
     Console.WriteLine(a);
     Console.WriteLine(b);

请注意,将b强制转换为int时,由于int无法容纳它,b被推回到MIN int。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接