【问题标题】:How can I compute a base 2 logarithm without using the built-in math functions in C#?如何在不使用 C# 中的内置数学函数的情况下计算以 2 为底的对数?
【发布时间】:2012-08-14 22:02:24
【问题描述】:

如何在不使用 C# 中的内置数学函数的情况下计算以 2 为底的对数?

我在一个应用程序中反复使用 Math.Log 和 BigInteger.Log 数百万次,它变得非常缓慢。

我对使用二进制操作来实现相同目的的替代方案感兴趣。请记住,如果有助于加快执行时间,我可以使用对数近似值。

【问题讨论】:

  • 给定一个整数,除了最重要的一位之外,您可以将所有位归零,并且您已经获得了 2 的幂,它有一个微不足道的 2 对数。这是一个非常粗略的近似值。
  • 有趣,我想知道找到最高有效位的最快方法是什么。
  • Levesque 有一个很好的解决方案。

标签: c# .net logarithm


【解决方案1】:

假设您只对对数的整数部分感兴趣,您可以这样做:

static int LogBase2(uint value)
{
    int log = 31;
    while (log >= 0)
    {
        uint mask = (1 << log);
        if ((mask & value) != 0)
            return (uint)log;
        log--;
    }
    return -1;
}

(注意,0 的返回值是错误的;它应该是负无穷大,但整数数据类型没有这样的值,所以我改为返回 -1)

【讨论】:

    【解决方案2】:

    【讨论】:

    • 虽然理论上可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
    【解决方案3】:

    对于 BigInteger,您可以使用 toByteArray() 方法,然后手动找到最重要的 1,然后计算零的数量。这将为您提供整数精度的以 2 为底的对数。

    【讨论】:

    • 完美。这将 CPU 周期减少到几乎 1 而不是 byte[].Length。 BigInteger 使这很容易。我想知道对于 Int32、Int64、double 等原生类型的方法是什么。
    • 好吧,从技术上讲,您可以对任何整数类型执行相同的排序操作。至于双精度数,它真的很容易,只要它是一个 IEEE 二进制双精度数,只需使用按位和运算来选择指数位并将它们移过来——有以二为底的对数。实际上,对于 IEEE 十进制来说也很容易。只需做同样的事情,然后除以 log2(10) = ~3.2。
    【解决方案4】:

    bit hacks 页面对这类事情很有用。

    代码在 C 中,但基本思想也适用于 C#。

    【讨论】:

      【解决方案5】:

      如果您可以使用近似值,那么请使用英特尔芯片使用的技巧:将值预先计算到合适大小的数组中,然后引用该数组。您可以使数组以任何最小值/最大值开始和结束,并且您可以根据需要创建任意数量的中间值以达到所需的精度。

      【讨论】:

        猜你喜欢
        • 2011-03-04
        • 2011-12-26
        • 1970-01-01
        • 2021-02-09
        • 2019-06-15
        • 1970-01-01
        • 1970-01-01
        • 2019-09-08
        • 1970-01-01
        相关资源
        最近更新 更多