【问题标题】:metaprogramming, factorial, C++, boost元编程、阶乘、C++、boost
【发布时间】:2015-05-26 17:20:16
【问题描述】:

需要对从 1 到 k 的所有数字进行阶乘,并使用 boost/mpl 将它们保存在 mpl 容器中。

存储在 range_c 中的这个数字的范围。 困难在于我必须存储所有以前的值: k! = (k-1)!*k

我以为我会将以前的值存储在 mpl::vector_c 中,即每次迭代我将从源 range_c 中获取值并将其与包含在 vector_c 中的先前值 (k-1)! 相乘,但是我在这方面有很多错误代码:

namespace mpl = boost::mpl;
const int border = 10;
using namespace mpl;

typedef
    range_c <int, 1, border>
Numbers;

typedef vector_c<int, 1> data;

typedef
   mpl::transform
  <
    Numbers,
    data,
    push_back<data, multiplies <_, _>>,
    back_inserter
    <
      mpl::vector <>
    >
  >::type
    Factorials;

【问题讨论】:

    标签: c++ boost metaprogramming


    【解决方案1】:

    在所有实现中,从 1 开始计算每个数字的阶乘。在任务中,我需要通过与前一个阶乘相乘来计算每个下一个阶乘。这里正确的代码:

    namespace mpl = boost::mpl;
    using namespace mpl;
    const int border = 15;
    
    typedef range_c<int, 1, border> nums;
    typedef vector<int_<1>> data;
    
    typedef mpl::fold<
        nums, data,
        mpl::push_back<_1, mpl::multiplies<_2, back<_1>>>
    >::type Factorials;
    

    【讨论】:

    • 你用什么来编译你的代码?对我来说,在 VS2013 和 gcc4.8.2 中使用 boost 1.56 编译失败
    • 这里所有的代码,如果有帮助的话。link我用 VS13 编译使用 boost 1.58
    【解决方案2】:

    您可以使用以下内容:

    namespace detail
    {
        // General computation of factorial
        template <std::size_t N>
        struct factorial :
            std::integral_constant<std::size_t, N * factorial<N - 1>::value>
        {
        };
    
        // special case for 0
        template <>
        struct factorial<0> : std::integral_constant<std::size_t, 1u>
        {};
    
        // helper to create the sequence of factorial value
        template <typename T> struct factorial_seq_impl;
    
        template <std::size_t...Is>
        struct factorial_seq_impl<std::index_sequence<Is...>>{
            using type = std::index_sequence<factorial<Is>::value...>;
        };
    
    }
    
    // And finally
    template <std::size_t N>
    using factorial_seq =
        typename detail::factorial_seq_impl<std::make_index_sequence<N>>::type;
    
    static_assert(std::is_same<std::index_sequence<1, 1, 2, 6, 24>, factorial_seq<5>>::value, "");
    

    Live Demo.

    【讨论】:

    • 我认为在这段代码中,每次从 1 开始计算每个数字的阶乘,我的意思是:1! = 1, 2! = 1 * 2, 3! = 1 * 2 * 3, ... 但我需要通过这个算法计算阶乘:1)计算 1!,2)保存 1!在容器中,3) 计算 2!使用 1!我们已经计算过了,没有必要再计算了,所以我们可以从容器中取:2! = 1!*2, 4) 节省 2!在容器中,5) 计算 3!使用 2!,我们已经计算过了,没有必要再计算了,所以我们可以从容器中取:3! = 2!* 3,但我该怎么做呢?无需重复计算即可计算阶乘
    • 全部实例化一次。所以目前,我将N 阶乘从0 实例化为N - 1,一个中间index_sequence&lt;0, .., N - 1&gt; 和结果index_sequence&lt;0!, 1!, (N - 1)!&gt;
    • 我明白.. 但是,也许您知道如何使用 boost 和 C++11 做到这一点?因为我的老师只需要 boost 并且对 C++14 非常进取。
    • @ДмитрийЕрмолаев:我在 C++14 中使用的唯一东西是 make_index_sequence,它可以很容易地用 C++11 编写。
    【解决方案3】:

    阶乘 mpl 版本和前 10 个结果的集合构成一个向量:

    template <typename current, typename to, typename result>
    struct calc :
        eval_if< less_equal< current, to >,
        calc< typename current::next, to, typename multiplies< result, current > >,
        result
        >::type
    {};
    
    template<typename value>
    struct factorial :
        calc<int_<1>, value, int_<1> >::type
    {};
    
    template <>
    struct factorial<int_<0> > :
        int_<1>::type
    {};
    
    template <>
    struct factorial<int_<1> > :
        int_<1>::type
    {};
    
    template <int value>
    struct factorial_c :
        factorial<int_<value> >::type
    {};
    
    struct factorial_collection_10 :
        transform<
        range_c<int, 0, 10>,
        factorial<boost::mpl::_1>,
        back_inserter<vector0<> >
        >::type
    {};
    

    测试代码:

    int main()
    {
        // get 5! value
        std::cout << "5! = " << factorial_c<5>::value << std::endl;
    
        // access 6th element of the factorial collection
        std::cout << "6! = " << at<factorial_collection_10, int_<6> >::type::value << std::endl;
    
        // copy factorial collection to std vector to check values at runtime
        std::vector<int> factorialVec;
        for_each< factorial_collection_10, boost::mpl::_1 >(boost::bind(static_cast<void(std::vector<int>::*)(const int&)>(&std::vector<int>::push_back), &factorialVec, boost::lambda::_1));
    
        std::cout << "First 10 factorial numbers: " << std::endl;
        for (std::size_t x = 0; x < factorialVec.size(); ++x)
            std::cout << x << "! = " << factorialVec[x] << std::endl;
    
        return 0;
    }
    

    输出:

    5! = 120
    6! = 720
    First 10 factorial numbers:
    0! = 1
    1! = 1
    2! = 2
    3! = 6
    4! = 24
    5! = 120
    6! = 720
    7! = 5040
    8! = 40320
    

    【讨论】:

      猜你喜欢
      • 2013-11-13
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      相关资源
      最近更新 更多