【问题标题】:How to check if std::ratio_multiply overflows?如何检查 std::ratio_multiply 是否溢出?
【发布时间】:2020-08-15 21:51:21
【问题描述】:

如果没有溢出,我需要一个函数,它会给我“std::ratio_multiply”类型,或者如果溢出,则为我提供原始比率类型列表。

【问题讨论】:

    标签: c++ templates stl metaprogramming template-meta-programming


    【解决方案1】:

    充分条件是检查分子和分母的对数总和是否小于std::numeric_traits<std::intmax_t>::max() 的对数,但这不包括一些会取消为可表示值的事物。

    这可以通过考虑 gcds 来改善

    template <typename R1, typename R2, bool>
    struct safe_ratio_multiply_impl;
    
    template <typename R1, typename R2>
    struct safe_ratio_multiply_impl<R1, R2, true>
    {
        using type = std::ratio_multiply<R1, R2>;
    }
    
    template <typename R1, typename R2>
    struct safe_ratio_multiply_impl<R1, R2, false>
    {
        using type = std::tuple<R1, R2>;
    }
    
    constexpr intmax_t log(intmax_t number, intmax_t acc = 0) {
        return number <= 1 ? acc : log(number / 2, acc + 1);
    }
    
    constexpr bool is_safe_multiple(std::intmax_t N1, std::intmax_t D1, std::intmax_t N2, std::intmax_t D2)
    {
        auto limit = log(std::numeric_traits<std::intmax_t>::max()) + log(std::gcd(N1, R2)) + log(std::gcd(N2, R1));
        auto num = (log(N1) + log(N2)) < limit;
        auto den = (log(R2) + log(R2)) < limit;
        return num && den;
    }
    
    template <typename R1, typename R2>
    using safe_ratio_multiply = typename safe_ratio_multiply_impl<R1, R2, is_safe_multiple(R1::num, R1::den, R2::num, R2::den)>::type;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 2012-11-19
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 2019-01-23
      相关资源
      最近更新 更多