C++11:ratio

C++11 中新增了一个 ratio 类,用来表示编译时的常量有理数。它在实际开发中很少单独使用,主要是搭配 <chrono> 库来表示有关时间的信息。

std::ratio

std::ratio 是一个模板类,定义如下:

template <intmax_t N, intmax_t D = 1> class ratio;

其中,intmax_t 为编译器所能支持的最大有符号整形数的类型,通常为:

typedef long long intmax_t;

std::ratio 使用分数的形式来表示一个数,或者说表示一个比例。模板参数 N 为分子,D 为分母,默认为1,ND 都必须在 intmax_t 的可表示范围内,并且分母 D 不能为0。

例如,ratio<1, 2>; 表示 1/2ratio<2, 3>; 表示 2/3

需要注意的是,ratio 是使用其类型来表示一个分数,而不是用该类型的一个对象实例来表示,并且这种表示只是编译时的。

ratio 类上还定义有两个公共成员变量,numden,分别为约分之后的分子和分母,由模板参数 ND除以它们的最大公约数的来。例如:

#include <iostream>;
#include <ratio>;

int main()
{
    typedef std::ratio<1, 2>; r1;
    typedef std::ratio<2, 4>; r2;
    typedef std::ratio<2, 3>; r3;
    typedef std::ratio<4, 6>; r4;

    std::cout << "r1= " << r1::num << "/" << r1::den << std::endl;
    std::cout << "r2= " << r2::num << "/" << r2::den << std::endl;
    std::cout << "r3= " << r3::num << "/" << r3::den << std::endl;
    std::cout << "r4= " << r4::num << "/" << r4::den << std::endl;

    // r1= 1/2
    // r2= 1/2
    // r3= 2/3
    // r4= 2/3
    return 0;
}

标准库中还预定于了一些 ratio 类型,

using atto  = ratio<1, 1000000000000000000>;;
using femto = ratio<1, 1000000000000000>;;
using pico  = ratio<1, 1000000000000>;;
using nano  = ratio<1, 1000000000>;;
using micro = ratio<1, 1000000>;;
using milli = ratio<1, 1000>;;
using centi = ratio<1, 100>;;
using deci  = ratio<1, 10>;;
using deca  = ratio<10, 1>;;
using hecto = ratio<100, 1>;;
using kilo  = ratio<1000, 1>;;
using mega  = ratio<1000000, 1>;;
using giga  = ratio<1000000000, 1>;;
using tera  = ratio<1000000000000, 1>;;
using peta  = ratio<1000000000000000, 1>;;
using exa   = ratio<1000000000000000000, 1>;;

标准库还提供了用于 ratio 运算的模板类:

ratio_add
ratio_subtract
ratio_multiply
ratio_divide

以上这些并不是函数,同样也是模板类,可以分别对 ratio 进行加减乘除运算,以 ratio_add 为例,它的定义为:

template 
using ratio_add = ratio < R1::num * R2::den + R2::num * R1::den, R1::den * R2::den >;;

使用示例如下:

#include <iostream>;
#include <ratio>;

int main ()
{
    typedef std::ratio<1, 2>; one_half;
    typedef std::ratio<2, 3>; two_thirds;

    typedef std::ratio_add<one_half, two_thirds>; sum;

    std::cout << "sum = " << sum::num << "/" << sum::den;
    std::cout << " (which is: " << ( double(sum::num) / sum::den ) << ")" << std::endl;

    return 0;
}

除此之外,标准库也定义了用于比较运算的模板类:

ratio_equal
ratio_not_equal
ratio_less;
ratio_less_equal
ratio_greater
ratio_greater_equal

它们也都是模板类,但详细定义稍有一些复杂,这里我们就不详细解释了,只需要了解它们通过公共成员value来获取比较的结果。例如:

#include <iostream>;
#include <ratio>;

int main ()
{
    typedef std::ratio<1, 2>; one_half;
    typedef std::ratio<2, 4>; two_fourths;

    std::cout << "1/2 == 2/4 ? " << std::boolalpha;
    std::cout << std::ratio_equal<one_half,two_fourths>;::value << std::endl;

    return 0;
}

以上就是有关 C++11 中新增的 ratio 的内容,一般情况下不太会直接使用到它,而是主要作为 chrono 库的基础。并且再次需要注意,ratio 的相关内容只能提供编译期的常量表示和计算,并不能提供运行时的表示和计算。

参考:

使用 Hugo 构建
主题 StackJimmy 设计