【问题标题】:Division to the nearest 1 decimal place without floating point math?除法到最接近的小数点后 1 位没有浮点数学?
【发布时间】:2010-04-11 00:47:24
【问题描述】:

我的 C# 程序遇到了一些速度问题,并确定此百分比计算导致速度变慢。计算很简单,n/d * 100。分子和分母都可以是任何整数。分子永远不会大于分母,也永远不会是负数。因此,结果始终为 0-100。现在,这是通过简单地使用浮点数学来完成的,而且速度有点慢,因为它被计算了数千万次。我真的不需要比最接近的 0.1% 更准确的东西。而且,我只是使用这个计算值来查看它是否大于一个固定的常数值。我在想一切都应该保持为整数,所以精度为 0.1 的范围是 0-1000。有没有什么方法可以在没有浮点数学的情况下计算这个百分比?

这是我用于计算的循环:

for (int i = 0; i < simulationList.Count; i++)
{
    for (int j = i + 1; j < simulationList.Count; j++)
    {
        int matches = GetMatchCount(simulationList[i], simulationList[j]);
        if ((float)matches / (float)simulationList[j].Catchments.Count > thresPercent)
        {
            simulationList[j].IsOverThreshold = true;
        }
    }
}

【问题讨论】:

  • 我认为这是一个相当稀疏/紧密的循环,可能会导致这样的瓶颈。我们能看到吗?
  • 我猜如果这真的是减慢程序速度的原因,缓存效果可能会发挥与整数和浮点数学之间的差异一样大的作用。此外,装箱/拆箱或其他任何可能导致分配的事情,我预计会比数学运算产生更大的影响。
  • 我刚刚将我正在使用的循环添加到消息中。
  • 我认为大部分时间都花在将变量转换为浮点数,而不是在除法上。

标签: c# floating-point integer division


【解决方案1】:

您可以使用n &gt; d * c(假设d &gt; 0)代替n/d &gt; c
c 是您要比较的常数值。)

这样你根本不需要除法。

但是,请注意溢出。

【讨论】:

  • 这很好,因为它甚至完全摆脱了除法,这通常比乘法更昂贵。
  • 如今,现代 CPU 上的除法和乘法成本相同。
  • @Loadmaster:整数乘法不是比从整数到浮点数和浮点除法的转换便宜吗?
  • @Loadmaster:那时我似乎有点过时了,因为我一直认为整数乘法比整数除法便宜。 @Vlad:是的,但是您也可以通过 (1000 * n) / d 进行整数除法
  • @Matti:优化编译器用整数乘法和位移位替换整数除法,因此成本没有差异。我很确定除以一个变量仍然比乘法慢几倍。
【解决方案2】:

如果您的单位是十分位而不是个,那么您可以使用整数算术获得 0.1 的精度:

代替:

for (...)
{
    float n = ...;
    float d = ...;

    if (n / d > 1.4) // greater than 140% ?

...做一些类似的事情:

for (...)
{
    int n = 10 * ...;
    int d = ...;
    if (n / d > 14) // greater than 140% ?

【讨论】:

  • 为了速度,请使用double 而不是float
【解决方案3】:

而不是写

if ((float)matches / (float)simulationList[j].Catchments.Count > thresPercent)

写这个:

if (matches * theresPercent_Denominator > simulationList[j].Catchments.Count * thresPercent_Numerator)

通过这种方式,您摆脱了浮点数。

注意:thresPercent可以表示为thresPercent_Numerator / theresPercent_Denominator,只要是有理数。)我认为这是PC上的最佳方式。对于其他一些平台,如果 theresPercent_Denominator 和/或 thresPercent_Numerator 是 2 的幂,您可以通过左移或右移进一步优化它。 (一般左移就够了,但可能需要通过重新排列除法来右移,以防止溢出)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 2021-04-23
    • 1970-01-01
    • 2022-11-22
    • 2016-12-13
    相关资源
    最近更新 更多