【问题标题】:What's the best way to calculate log(base2) of any number?计算任何数字的 log(base 2) 的最佳方法是什么?
【发布时间】:2014-06-09 09:57:36
【问题描述】:

我需要在 Linux 内核编程中找到任意数量的 log(base2)。 此操作是否有任何内置功能? 如果不是怎么计算呢?

【问题讨论】:

    标签: c linux linux-kernel linux-device-driver


    【解决方案1】:

    如果整数结果对你来说足够了,你可以多次除以 2。类似

    int logFunc(unsigned int x) 
    { 
       int log = -1; 
       while(x) { 
        log++; 
        x >>= 1; 
       } 
       return log; 
    } 
    

    如果您需要 fp 操作,您应该阅读以下内容:

    [...]如果问题是“我可以在内核中使用 FP”,那么 答案仍然是一个响亮的 NO,因为其他架构可能不会 完全支持。

      Linus
    

    Link

    另外,您可以查看:Use of floating point in the Linux kernel

    编辑:如果您需要更快的版本,您可以阅读Bit Twiddling Hacks - By Sean Eron Anderson

    uint32_t v; // find the log base 2 of 32-bit v
    int r;      // result goes here
    
    static const int MultiplyDeBruijnBitPosition[32] = 
    {
      0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
      8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
    };
    
    v |= v >> 1; // first round down to one less than a power of 2 
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    
    r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
    

    【讨论】:

    • 这里快速除以二的好方法是 >> 对设置为 1 的 unsigned int 的最大位进行二进制搜索。
    • @Alex 感谢您的评论。我已经添加了一个具有良好实现的资源。
    • 这些解决方案可以很好地找到整数的 log(base2)。但我还需要找到非整数的 log(base2)。
    • 这是有问题的。你想完成什么?
    • 我需要找到时钟频率对应的值。如果频率可以表示为 2 的幂,则您的方法有效。
    【解决方案2】:

    根据定义,数字 N 在任何特定底数 B 中的对数等于 log(N)/log(B),其中 log() 可以是自然对数(底数 e)或任何其他底数(例如底数 10) ,只要 log(N)log(B) 都是针对相同的基数计算的。

    【讨论】:

    • 要包含哪个头文件?
    • 这是针对 Linux 内核代码的。我不相信有一个数学标题...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 2015-08-21
    • 1970-01-01
    • 2010-09-13
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多