(QQ:114211200)
std::ratio代表一个比例,或者说比率。其实就是将给定的两个整数分别除以它们的最大公约数得到一个分数(分子及分母)。其定义为(vs2015):
template<intmax_t _Nx, intmax_t _Dx = 1>
struct ratio
{ // holds the ratio of _Nx to _Dx
static_assert(_Dx != 0, "zero denominator");
static_assert(-INTMAX_MAX <= _Nx, "numerator too negative");
static_assert(-INTMAX_MAX <= _Dx, "denominator too negative");
static constexpr intmax_t num = _Sign_of<_Nx>::value
* _Sign_of<_Dx>::value * _Abs<_Nx>::value / _Gcd<_Nx, _Dx>::value;
static constexpr intmax_t den = _Abs<_Dx>::value / _Gcd<_Nx, _Dx>
::value;
typedef ratio<num, den> type;
};
附加部分类型以及宏的定义:
typedef long long intmax_t;
#define INTMAX_MAX INT64_MAX
std::ratio具有2个intmax_t的非类型模板参数,_Nx代表分子(numerator),_Dx代表分母(denominator)。_Dx不可以为0,_Nx和_Dx都不可以小于-INTMAX_MAX。
num和den分别代表_Nx和_Dx除以它们的最大公约数得到的商。
类型type代表换算后的ratio类型。因此ratio<1,2>::type、ratio<4,8>::type、ratio<3,6>::type都是相同的类型。
STL还定义了一些类型(vs2013):
typedef ratio<1, 1000000000000000000LL> atto;
typedef ratio<1, 1000000000000000LL> femto;
typedef ratio<1, 1000000000000LL> pico;
typedef ratio<1, 1000000000> nano;
typedef ratio<1, 1000000> micro;
typedef ratio<1, 1000> milli;
typedef ratio<1, 100> centi;
typedef ratio<1, 10> deci;
typedef ratio<10, 1> deca;
typedef ratio<100, 1> hecto;
typedef ratio<1000, 1> kilo;
typedef ratio<1000000, 1> mega;
typedef ratio<1000000000, 1> giga;
typedef ratio<1000000000000LL, 1> tera;
typedef ratio<1000000000000000LL, 1> peta;
typedef ratio<1000000000000000000LL, 1> exa;
下面看示例代码:
template<typename T>
void output(const T &t)
{
cout << typeid(t).name() << ":" << endl;
cout << "num:" << t.num << endl;
cout << "den:" << t.den << endl;
}
void call_by_main()
{
ratio<2, 4> r;
output(r);
ratio<1, 3> r1;
output(r1);
ratio<3, 6> r3;
output(r3);
system("pause");
}
输出为:
struct std::ratio<2,4>:
num:1
den:2
struct std::ratio<1,3>:
num:1
den:3
struct std::ratio<3,6>:
num:1
den:2
请按任意键继续. . .
STL还定义了一些辅助运算用的模板类。
其中一些以类型的方式提供了2个ratio类型的各种算数运算结果。注意,是类型的运算,得到的结果当然也是类型,通常为x::type的形式。
另外一些以值的方式提供了2个ratio类型的关系运算结果,这个结果是值,通常为x::value的形式。
这些类型有:
名称 | type 值 |
---|---|
ratio_add | R1 + R2 |
ratio_divide | R1 / R2 |
ratio_equal | R1 == R2 |
ratio_greater | R1 > R2 |
ratio_greater_equal | R1 >= R2 |
ratio_less | R1 < R2 |
ratio_less_equal | R1 <= R2 |
ratio_multiply | R1 * R2 |
ratio_not_equal | !(R1 == R2) |
ratio_subtract | R1 - R2 |
以std::ratio_add来说,它的作用是求出两个ratio类型的和的类型, 它的定义如下:
template<class _R1,
class _R2>
struct _Ratio_add
{ // add two ratios
static_assert(_Are_ratios<_R1, _R2>::value,
"ratio_add<R1, R2> requires R1 and R2 to be ratio<>s.");
static constexpr intmax_t _N1 = _R1::num;
static constexpr intmax_t _D1 = _R1::den;
static constexpr intmax_t _N2 = _R2::num;
static constexpr intmax_t _D2 = _R2::den;
static constexpr intmax_t _Gx = _Gcd<_D1, _D2>::value;
// typename ratio<>::type is necessary here
typedef typename ratio<
_Safe_add<
_Safe_mult<_N1, _D2 / _Gx>::value,
_Safe_mult<_N2, _D1 / _Gx>::value
>::value,
_Safe_mult<_D1, _D2 / _Gx>::value
>::type type;
};
template<class _R1,
class _R2>
using ratio_add = typename _Ratio_add<_R1, _R2>::type;
使用示例:
template<typename T>
void output(const T &t)
{
cout << typeid(t).name() << ":" << endl;
cout << "num:" << t.num << endl;
cout << "den:" << t.den << endl;
}
void call_by_main()
{
ratio<2, 4> r;
output(r);
ratio<1, 3> r1;
output(r1);
//求和的类型:
ratio_add<decltype(r), decltype(r1)> sum;
output(sum);
//第一个类型是否大于第二个类型:
using gr = ratio_greater<decltype(r), decltype(r1)>;
cout << "gr::value_type:" << typeid(gr::value_type).name() << endl;
cout << "gr::value:" << gr::value << endl;
system("pause");
}
输出为:
struct std::ratio<2,4>:
num:1
den:2
struct std::ratio<1,3>:
num:1
den:3
struct std::ratio<5,6>:
num:5
den:6
gr::value_type:bool
gr::value:1
请按任意键继续. . .