2018年11月18日 星期日

C++ 學習筆記:ratio

Compile-time 的分數與算術運算

Hello World Example:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <ratio>
#include <cstdint>

int main()
{
    /* Representation */
    using FiveThirds = std::ratio < 5, 3 > ;
    std::cout << FiveThirds::num << "/" << FiveThirds::den << std::endl;            // 5/3

    using AlsoFiveThirds = std::ratio < 25, 15 >;
    std::cout << AlsoFiveThirds::num << "/" << AlsoFiveThirds::den << std::endl;    // 5/3

    std::ratio<42, 42> one;
    std::cout << one.num << "/" << one.den << std::endl;                            // 1/1

    using Zero = std::ratio<0>;  // denominator default 1
    Zero zero;
    std::cout << zero.num << "/" << zero.den << std::endl;                          // 0/1

    using Neg = std::ratio < 7, -3 >;
    std::cout << Neg::num << "/" << Neg::den << std::endl;                          // -7/3

    /* Arithmetics: meta functions */
    using Addtype = std::ratio_add<FiveThirds, AlsoFiveThirds>::type;
    std::cout << Addtype::num << "/" << Addtype::den << std::endl;                  // 10/3

    std::cout << std::boolalpha
              << std::ratio_equal<FiveThirds, AlsoFiveThirds>::value << std::endl;  // true

    //std::ratio_multiply < std::ratio<1, INTMAX_MAX>, std::ratio<1, 2> >;          // compile error
    //std::ratio_divide<FiveThirds, Zero>;                                          // compile error
    //std::ratio_divide<FiveThirds, Zero>::type;                                    // compile error

    /* Predefined units */
    using NanoType = std::ratio<1, 1000000000LL>::type;
    std::cout << std::boolalpha << std::ratio_less<std::nano, NanoType>::value << std::endl;// false
    std::cout << std::boolalpha << std::ratio_less<NanoType, std::nano>::value << std::endl;// false
    std::cout << std::boolalpha << std::ratio_equal<std::nano, NanoType>::value << std::endl;// true
}


class 大致定義如下:



#include <cstdint>
namespace std
{
    template <intmax_t N, intmax_t D = 1>
    struct ratio {
        static_assert(D != 0, "denominator cannot be zero");
        static_assert(N >= -INTMAX_MAX && D >= -INTMAX_MAX, "out of range");

        static constexpr intmax_t num = ...;
        static constexpr intmax_t den = ...;
        
        using type = ratio < num, dem > ;
    };
}


  • 主要用途為在 compile time 表示一組分數
  • 在編譯期可自動抓取 divide-by-zero 與 overflow 的錯誤
  • 常被使用在 chrono 上

使用方法:

  1. 給定分子與分母,定義一個 type(可使用 using)
  2. 使用 static constexpr 的 num 與 den
  3. Predefine 的 unit 可參考此 Link

Reference:

  1. The C++ Standard Library: A Tutorial and Reference, Second Edition
  2. https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01002_source.html
  3. Visual Studio 2013 Library

沒有留言:

張貼留言