使用Math.Floor比显式整数转换有什么好处吗?

12
问题非常简单,有没有任何好处或区别?我注意到在C#中,该函数返回一个没有小数位的double类型,而在Java中它保留小数位,但除此之外,结果是相同的。
以下是我在Java和C#中使用的代码以及输出:
//Java                                        //C#

double a = 5.5;                               double a = 5.5;
System.out.println(Math.floor(a));            Console.WriteLine(Math.Floor(a));
System.out.println((int)a);                   Console.WriteLine((int)a);

//Output                                      //Output

5.0                                           5
5                                             5

2
Java会在所有浮点数后面打印.0吧。 - Willem Van Onsem
你基于System.out的输出做出了“Java会保留”的假设?这是错误的假设。 - Iłya Bursov
2
Math.Floor 返回一个没有小数部分的双精度浮点数。这与强制转换为整数不同。 - Claudio Redi
2
可能是重复的问题,链接为https://dev59.com/9Wkw5IYBdhLWcg3wkLX2。 - Hamid Pourjam
int的可能最小值比floatdouble要低。 - Matthew
@Matthew:好观点,已将其插入答案中。 - Willem Van Onsem
1个回答

22

是的,对于负数,这个方法的工作方式是相反的。

示例(使用Mono的C#交互式shell csharp):

csharp> Math.Floor(-12.0d)
-12
csharp> Math.Floor(-12.5d) 
-13
csharp> (int) -12.5
-12

(Java/C# 都一样)我猜大多数编程语言都是这样。将浮点数强制转换为整数,会丢掉小数部分并保留整数部分。-12.5 的整数部分是 12。因此,如果将负数转换为 int,则会执行 Math.Ceil 操作。

此外,正如 @Matthew 所说,float 或 double 可以达到像 1.023e23(阿伏伽德罗常数)这样的数字。这只是因为底数不能再表示逗号后面的数字了。这些数字仍然被认为是整数,但不能由 int 表示。通过执行 Math.floor 操作,不会发生任何事情,但值仍然保持不变。而转换为 int 可能导致溢出:

示例

csharp> double ac = 1.023e23;
csharp> Math.Floor(ac);
1.023E+23
csharp> (int) ac;
0

注意:这可能看起来有些牵强,但语义上仍然存在明显的区别。无论如何,这种差异往往会导致错误。
此外,对于无限数字和NaN,它工作方式不同
System.out.println(Math.floor(Double.POSITIVE_INFINITY)); // Prints Infinity
System.out.println((int)Double.POSITIVE_INFINITY);        // Prints 2147483647
System.out.println(Math.floor(Double.NaN));               // Prints NaN
System.out.println((int)Double.NaN);                      // Prints 0

但我仍然会使用它们。强制转换使事情变得更难读。向上/向下/四舍五入更像是强制转换的一种(副作用)。通过使用Math.Ceil/Floor/Round,可以清楚地表达您的意思。

有时将其转换为整数比先执行floor/ceil操作要更有效率一些。但是聪明的编译器有时可以推导出一个变量将始终存储正数,并因此自行进行优化。而且对于大多数应用程序,这将导致无关紧要的性能损失。


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