【问题标题】:What's the right way to compute integral base-2 logarithms at compile-time?在编译时计算以 2 为底的整数对数的正确方法是什么?
【发布时间】:2016-05-20 14:22:14
【问题描述】:

我有一些来自与我不同的库的正常量值,称之为the_val。现在,我希望 log_of_the_val 成为 floor(log_2(the_val)) - 不是用 C++ 代码说话 - 当然,我希望这发生在编译时。

现在,有了 gcc,我可以做类似的事情

decltype(the_val) log_of_the_val = sizeof(the_val) * CHAR_BIT - __builtin_clz(the_val) - 1;

我认为这应该可行(长度 - 标题零的数量)。否则,我可以自己为它实现一个 constexpr 函数,但我敢打赌,我可以在编译时使用其他的、更简单、更便携的东西。 ...问题是,那会是什么?

【问题讨论】:

    标签: c++11 constants constexpr logarithm idioms


    【解决方案1】:

    最直接的解决方案是使用<cmath> 中的std::log2,但未指定为 constexpr - 它在 gcc 下,但不在 clang 下。 (其实libstdc++std::log2调用__builtin_log2,就是gcc下的constexpr。)

    __builtin_clz 在 gcc 和 clang 下都是 constexpr,所以你可能想要使用它。

    完全可移植的解决方案是写一个递归的 constexpr 积分 log2:

    constexpr unsigned cilog2(unsigned val) { return val ? 1 + cilog2(val >> 1) : -1; }
    

    【讨论】:

    • -1 的基本原理是什么?另外,修复了我认为的 off-by-1。
    • @einpoklum log2(0) 是一个错误,但它简化了返回 -1 的实现。另一种方法是终止1 上的递归,并为0 抛出std::domain_errorconstexpr unsigned cilog2(unsigned val) { return val > 1 ? 1 + cilog2(val >> 1) : val == 1 ? 0 : throw std::domain_error{"cilog2(0)"}; }
    猜你喜欢
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    相关资源
    最近更新 更多