【发布时间】:2014-10-15 00:01:36
【问题描述】:
我对这种情况的假设是否正确:
double d = 3.76212; // d >= 0 && d <= Int32.MaxValue
应该始终使用这个:
double truncated = (double)(int)d;
代替以下任何一种:
double truncated = Math.Truncate(d); // 4 times slower than (double)(int) on x86, 7 times slower than (double)(int) on x64
double truncated = Math.Floor(d); // 3 times slower than (double)(int) on both x86 and x64
换句话说,只有在处理足够大的数字时(>Int32.MaxValue on x86 和 > Int64.MaxValue onx64),或者在处理小于 0 的数字时,才会使用 Math.Floor,因为 Floor 对负数的行为不同?至于 Truncate,它的使用确实应该受到限制(缺少无法放入 Int32 或 Int64 的非常大的负数),因为它在所有情况下都比 Floor 慢?
【问题讨论】:
-
我会换一种说法:而不是 One should always use...,我会说:如果双截断是应用程序中的瓶颈,请使用
(double)(int)d。如果不是,请使用使您的代码意图对您的同事和您未来的自己尽可能清晰的任何方法。 -
int始终是Int32,无论系统是 x86 还是 x64。所以double truncated = (double)(int)d;对于d > Int32.MaxValue总是会失败(或更糟:溢出并返回负值)。 -
@Corak 是的,我知道。但是如果你为 AnyCpu 或 x64 编译并在 64 位 CPU 上运行,你可以使用 (double)(long)d 甚至比 (double)(int)d 性能更好。
-
这是一个有效的微优化,可以内联生成强制转换的机器代码,数学函数需要调用 CLR 辅助方法。需要几纳秒的时间。请记住,演员表在溢出时会生成可怕的数据,获取 Int32.MinValue 并没有什么好说的。结果是纯粹的垃圾,没有很好的检测方法。
标签: c# .net performance math type-conversion