【问题标题】:Math.Floor or Math.Truncate vs (int) in terms of Performance for Positive Numbers正数性能方面的 Math.Floor 或 Math.Truncate vs (int)
【发布时间】: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 &gt; Int32.MaxValue 总是会失败(或更糟:溢出并返回负值)。
  • @Corak 是的,我知道。但是如果你为 AnyCpu 或 x64 编译并在 64 位 CPU 上运行,你可以使用 (double)(long)d 甚至比 (double)(int)d 性能更好。
  • 这是一个有效的微优化,可以内联生成强制转换的机器代码,数学函数需要调用 CLR 辅助方法。需要几纳秒的时间。请记住,演员表在溢出时会生成可怕的数据,获取 Int32.MinValue 并没有什么好说的。结果是纯粹的垃圾,没有很好的检测方法。

标签: c# .net performance math type-conversion


【解决方案1】:

我认为我们不能假设在未来版本的框架或未来版本的 CLR 中总是如此。

您可以做的是创建一个您调用的简单助手类,然后在该类中隐藏实现细节。然后,当新的 CLR/框架出现时,您可以重新进行测量并在需要时更新帮助程序类:

double truncated = FastMath.Truncate(d);

并按照以下方式实施

public static double Truncate(double d)
{
    if ((d >= Int32.MinValue) && (d <= Int32.MaxValue))
    {
        ...
    }
}

【讨论】:

  • 好主意!但这仍然是一个函数调用,如果你调用它十亿次,它的成本就会很高。所以我想现在,考虑到测量结果,可以安全地假设应该使用 (double)(int)。我也很难想象像这样的内联转换会比函数调用(在未来)变得更慢。
猜你喜欢
  • 2010-09-05
  • 2019-07-04
  • 2012-03-17
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 2012-12-02
  • 2013-08-13
  • 2019-10-09
相关资源
最近更新 更多